2017-10-05 1 views
2

내가 여기에 CRTP 템플릿 클래스가 있습니다그 소리가 : constexpr 변수가 가질 수없는 비 문자 유형

template <typename S> 
class Base 
{ 
    public: 
    constexpr static S NOT_SET{0}; 
}; 

struct Derived : public Base<Derived> 
{ 
}; 

연타 (5.0.0)이이 동의하지 않습니다

5 : <source>:5:24: error: constexpr variable cannot have non-literal type 'const Derived' 
    constexpr static S NOT_SET{0}; 
        ^
8 : <source>:8:25: note: in instantiation of template class 'Base<Derived>' requested here 
struct Derived : public Base<Derived> 
         ^
5 : <source>:5:24: note: incomplete type 'const Derived' is not a literal type 
    constexpr static S NOT_SET{0}; 
        ^
8 : <source>:8:8: note: definition of 'Derived' is not complete until the closing '}' 
struct Derived : public Base<Derived> 
    ^
1 error generated. 
Compiler exited with result code 1 

그러나 gcc (4.9.2와 6.2에서 테스트)는 괜찮습니다.

clang에서이 작업을 수행하는 방법은 무엇입니까?

답변

2

Derived은 클래스 템플릿 Base에서 사용할 때 완전한 유형이 아니므로 실제로는 사용할 수 없습니다. 그 유형의 변수를 선언 할 수 있으려면 유형이 완료되어야하기 때문입니다. 주위를 해결할 방법이 없습니다.
요약하면 } (그리고 회원 기능과 같이 케이스와 관련이없는 예외) 유형에서 유형이 완료됩니다.
이 표준은 (working draft을) 말씀입니다 :

클래스는 클래스 지정자의 폐쇄}에서 완전히 정의 객체 유형 (또는 완전 형)으로 간주됩니다.
클래스 멤버 지정 내에서 클래스는 함수 본문, 기본 인수, noexcept 지정자 및 기본 멤버 초기화 프로그램 (중첩 클래스의 클래스 포함) 내에서 완전하다고 간주됩니다.
그렇지 않으면 자체 클래스 멤버 지정 내에서 불완전한 것으로 간주됩니다.

따라서 clang은 옳고 오류는 다소 같습니다.


주석에서 언급했듯이이를 해결하는 방법이 있습니다. 파생 형식이 constexpr 구성 가능 인 경우, 을 반환하지 않는 기본 클래스에서 constexpr 함수를 정의 할 수 있습니다 (의미가 무엇이든간에).

+0

고마워요. 그러나 GCC의이 "기능"을 악용하는 기존 코드베이스를 포팅하려는 경우, 귀하의 충고는 무엇입니까? – Anton

+1

파생 된 유형이 constexpr 구성 가능하면, 기본 클래스에서 _not set_ 버전을 반환하는 constexpr 함수를 정의 할 수 있습니다 (의미하는대로). 그것은 당신을 위해 일할 수 있을까요? – skypjack

+0

네, 좋은 생각입니다. 고맙습니다. 나는 당신의 대답을 받아 들일 것이지만, 당신은 후손을 위해 당신의 대답을 대답에 넣을 수 있다고 생각합니까? :-) – Anton

관련 문제