2013-03-30 5 views
4

는 내가 모든 오류를 이해하지 못하는 내가이 코드가 "템플릿 특수화에 '템플릿 <>'이 필요합니까?라는 오류가 표시되는 이유는 무엇입니까?

error: template specialization requires 'template<>' 
Field<Class> const CRTP<Class>::_field("blah"); 
        ~~~~~~~~~~~^

을 얻을 연타

template<class T> 
struct Field 
{ 
    char const *name; 
    Field(char const *name) : name(name) { } 
}; 

template<class Derived> 
class CRTP { static Field<Derived> const _field; }; 

class Class : public CRTP<Class> { }; 
Field<Class> const CRTP<Class>::_field("blah"); 

int main() { } 

이것을 컴파일하려고하면. _field에 대한 내 정의가 잘못되었으며 어떻게 수정합니까?

(_field에 인수가 반드시 모든 서브 클래스 동일하지 않습니다.)

+0

당신이 템플릿을 붙이는 시도 되세요을 <>? –

+0

@AlexChamberlain : 하하 아니요, 저는 전문성과 관련이없는 것을 이해하지 못합니다. 왜냐하면 제가 전문적으로 전문성을 발휘하지 못했기 때문입니다. – Mehrdad

+1

@Mehrdad : 글쎄, 사실, 클래스 템플릿 클래스의'정적 '데이터 멤버를 전문으로하고있다. (멤버 함수처럼 17.4.3/1'static' 데이터 멤버가 특수화 될 수있다.) –

답변

11

을 컴파일러의 경우 (예 : 구문을 검사 할 수있는) 템플릿 전문으로 식별 할, 당신은 template 필요 키워드 :

template<> 
Field<Class> const CRTP<Class>::_field("blah"); 

그 괄호가 모든 템플릿 매개 변수가 전문이기 때문에 비어있는,하지만 당신은 단지 그것을 멀리 떠날 수 없다.

2

오류가 무엇인지 정확히 설명합니다. 해당 줄 앞에 template<>이 없습니다.

template<> 
Field<Class> const CRTP<Class>::_field("blah"); 

참고 그러나, Field<Class>의 타이핑 것으로, 고유의 경우, 주어진 문자열로 Field<Class>의 모든 인스턴스를 생성하는 데 사용할 수 있습니다. Field<Class>의 모든 인스턴스는 항상 이름 "blah"을 가지고 있다는 것을 의미

template<typename T> 
struct field_trait; 

template<class T> 
struct Field 
{ 
    char const *name; 
    Field() : name(field_trait<T>::get_name()) {} 
}; 

template<class Derived> 
class CRTP { static Field<Derived> const _field; }; 
template<class Derived> 
class CRTP<Derived>::_field; 

class Class; 

template<> 
struct field_traits<Class> { 
    static const char* get_name() { return "blah"; } 
}; 

class Class : public CRTP<Class> { }; 

int main() { } 

.

내가 가지고있는 질문 중 하나는 실제적으로 문자열에 대한 포인터를 가지고 있다고 말하면 Field<Class>의 저장소가 필요하며 그렇다면 고유해야하며, 그렇다면 "맨"이어야한다는 것입니다. static 인스턴스가있는 곳을 파악하는 것이 다소 성가심입니다. 상기 field_traits 함께

:

template<class Derived> 
class CRTP { static Field<Derived>& field() const { static Field<Derived> _field(field_traits<Derived>::get_name()); return _field; }; 

이 컴파일러 문제로되는 "어디 저장된 _field하다"의 문제를 이동시킨다. 그리고 field_traits<T>::get_name()의 내용으로 초기화됩니다.

+0

아니요, 정말 * 정적 *과 같은 정적 필드가 필요합니다. 필요한 곳 ​​(예 : 공장 등록 중 하나)의 예를 보려면 [여기] (http://stackoverflow.com/a/1310392/541686)를 참조하십시오. – Mehrdad

2

정적 데이터 멤버에는 선언과 정의가 모두 있어야합니다. 당신을 당신의 코드에서

// header: 
template <class T> 
class C { 
    static int i; 
}; 

template <class T> 
int C<T>::i = 3; 

:

// header: 
class C { 
    static int i; 
}; 

// source: 
int C::i = 3; 

템플릿은 일반적으로 소스 파일에 정의되지 않은, 그래서 코드는 다음과 같이 보일 것이다 :이 일반 클래스 인 경우는 다음과 같을 것 정적 데이터 멤버의 정의가 없습니다. 당신이 그것을 사용하지 않는다면 그건 괜찮아. 그러나 컴파일러가 불평하는 코드는 CRTP<Class>에 대한 정적 데이터 멤버를 정의합니다. 이것은 전문화 된 것입니다. (왜냐하면 CRTP의 모든 인스턴스화에는 적용 할 수 없기 때문입니다.) 컴파일러는 전문화라고 말해야한다고 말합니다.

template <> 
Field<Class> const CRTP<Class>::_field("blah"); 

하거나, 일반적인 템플릿 구문, 비 전문 템플릿 버전을 쓰기 사용 : : 그래서 당신이 말한 것 같이 할

template <class T> 
Field<T> const CRTP<T>::_field("blah");