constexpr 변수가 캡처되지 않았습니다.

Dec 10 2020

다음 코드는 clang에서 컴파일되지 않습니다 (GCC에서 수행됨).

struct A{
    int a;
};

auto test(){
    constexpr A x{10};
    return []{
        return x; // <-- here x is A: clang doesn't compile
    }();
}

Clang의 오류는 'x'변수capture-default가 지정되지 않은 람다에서 암시 적으로 캡처 할 수 없다는 것입니다 .하지만 constexpr 변수는 항상 캡처되었다고 생각했습니다.

x가 int이면 코드는 다음과 같이 컴파일됩니다.

auto test(){
    constexpr int x{10};
    return []{
        return x; // <-- here x is int: clang is ok
    }();
}

흥미롭게도 다음 코드도 컴파일됩니다.

auto test(){
    constexpr A x{10};
    return []{
        return x.a;
    }();
}

clang이 맞습니까? 그렇다면 그 이유는 무엇입니까? -std = c ++ 17을 사용하고 있습니다.

--편집하다--

다음 질문 : 캡처하지 않고 람다에서 constexpr 값을 사용할 수 있습니까? clang11에서는 더 이상 문제가되지 않으므로이 항목과 관련이 없습니다. 실제로 위에서 언급했듯이 x가 int이면 clang11이 컴파일됩니다.

샘플 코드도 있습니다. https://godbolt.org/z/rxcYjz

답변

2 DavisHerring Dec 25 2020 at 07:09

당신이 때 return x;첫 번째 예를 들어, 당신은 호출해야합니다 A바인딩 포함의 복사 생성자, 참조x따라서 ODR-사용을. 상수 표현식에서 사용할 수있는 값의 사소한 복사본이 더 이상 odr-use를 구성해서는 안된다는 주장을 할 수 return x.a;있지만 해당 규칙에는 그러한 예외가 없으므로 Clang은이 를 거부하는 것이 맞습니다 .

실제적으로, 캡처 할 필요가 없도록 모든 constexpr변수 static를 만들 수 있습니다 .