2013-07-16 1 views
19

CRTP와 함께 템플릿 템플릿 매개 변수를 사용하는 경우 파생 초기화 목록에서 기본 클래스 생성자를 호출 할 때 컴파일 오류가 발생합니다.clang ++ CRTP를 사용할 때 템플릿 템플릿 매개 변수 사용을 허용하지 않습니다.

문제는이 코드 조각으로 복제 할 수 있습니다

template <template<class> class Derived, class T> 
struct base 
{ 
}; 

template <class T> 
struct derived : public base<derived, T> 
{ 
    derived() 
     : base<derived, T>() 
    { } 
}; 

기분을 상하게하는 오류 님에게 메일 :

이 문제는 그 소리 (3.4)에 일이 나타납니다
bug.cpp:10:16: error: template argument for template template parameter must be a class template or type alias template 
     : base<derived, T>() 
      ^
bug.cpp:10:11: error: expected class member or base class name 
     : base<derived, T>() 
     ^
bug.cpp:10:11: error: expected '{' or ',' 
3 errors generated. 

하지 g ++ (4.8, 4.7, 4.6). 나는 -std = C++ 11로 컴파일하고있다.

템플릿 템플릿 매개 변수와 함께 CRTP를 사용해야하는 것은 이번이 처음입니다. 나는이 일을 잘하고 clang ++의 문제인가?

나는 clang ++ 오류 메시지가 g ++ 이상으로 늦어졌습니다.

답변

17

코드는 유효합니다. 는 C++ 11

표준, 섹션 14.6.1 :

정상 (비 템플릿) 클래스와 같이, 클래스 템플릿 주입 된 클래스 이름 (9 절)를 가지고있다. injection-class-name은 템플릿 이름 또는 유형 이름으로 사용할 수 있습니다. 템플릿 인수 목록에 을 템플릿 템플릿 매개 변수의 템플릿 인수로 사용하거나 친구 클래스 템플릿 선언의 구체화 된 유형 지정자의 최종 식별자로 사용하는 경우 이 참조됩니다 클래스 템플릿 자체에. clang의 버전이 여전히 이전 규칙을 구현하는 것처럼

보인다. 추가 의견에 따라 ctor-initializer-list에서만 그렇게 할 수 있습니다.


사용자 David Rodríguez - dribeas 완전히 C++ (11) 주입 수준의 이름 규칙을 구현하지 않은 컴파일러에 대한 해결 방법을 제공했다. 예를 들어, 자격이없는 클래스의 이름을 사용

derived() 
    : base< ::derived, T >() 
//   ^^ qualified with global namespace 
{ } 

어떤 컴파일러는 상속 목록이 필요할 수 있습니다 :

template <class T> 
struct derived : public base< ::derived, T > 
//       ^^ 
1이이 C에서 변경 한 것을 몰랐
+0

++ 11. 지금 삭제 된 답변에 대한 해결책을 제공 할 수 있습니다. –

+0

@ DavidRodríguez-dribeas : 걱정 마세요. 새로운 표준은 여전히 ​​자주 저를 놀라게합니다. –

+1

나는 반대로 나는 배웠다. 나는 무언가를 배웠다. 나는 새로운 것을 배울 수없는 날을 걱정할 것입니다. –

관련 문제