이상한 언어 문제는 CWG 1581입니다 .
15 절 [특별]은 특수 멤버 함수가 사용시에만 암시 적으로 정의된다는 것을 완벽하게 명확하게 알 수 있습니다. 이것은 평가되지 않은 컨텍스트에서 상수 표현식에 대한 문제를 만듭니다.
struct duration {
constexpr duration() {}
constexpr operator int() const { return 0; }
};
// duration d = duration(); // #1
int n = sizeof(short{duration(duration())});
여기서 문제는 우리 constexpr duration::duration(duration&&)
가이 프로그램에서 암시 적으로 정의 할 수 없으므로 초기화 목록의 표현식이 상수 표현식이 아닙니다 (정의되지 않은 constexpr 함수를 호출하기 때문에) 따라서 프로그램이 잘못 구성되었습니다.
1 행의 주석을 해제하면 이동 생성자가 암시 적으로 정의되고 프로그램이 유효합니다. 멀리서이 무시 무시한 행동은 매우 불행합니다. 이 시점에서 구현이 다양합니다.
나머지 문제 설명을 읽을 수 있습니다.
이 문제에 대한 해결책 은 2017 년 앨버 커키 P0859 (C ++ 17 출하 후)에 채택되었습니다 . 이 문제는 C ++ 20 모두에 대해 ( P0879constexpr std::swap
에서 해결됨 ) 및 constexpr std::invoke
( PWG65 에서 CWG1581 예제가 있는 P1065 에서 해결됨 ) 둘 다 가질 수있는 차단제였습니다 .
내 생각에 가장 이해하기 쉬운 예는 P1065에서 지적한 LLVM 버그 보고서의 코드입니다.
template<typename T>
int f(T x)
{
return x.get();
}
template<typename T>
constexpr int g(T x)
{
return x.get();
}
int main() {
// O.K. The body of `f' is not required.
decltype(f(0)) a;
// Seems to instantiate the body of `g'
// and results in an error.
decltype(g(0)) b;
return 0;
}
CWG1581은 constexpr 멤버 함수가 정의 된 시점 에 관한 것이며 해상도는 사용시에만 정의되도록합니다. P0859 이후에는 위의 형식이 양호합니다 (유형은 b
입니다 int
).
이후 std::swap
와 std::invoke
모두하는 멤버 함수에 대한 (이전의 이동 건축 / 할당하고 호출 연산자 / 후자의 대리 전화), 그들은 모두이 문제의 해결에 의존 확인에 의존해야합니다.