2010-10-16 3 views
6

Скажем, у меня есть следующий класс:Как классифицировать статический член класса шаблона на шаблонном типе?

template<class T> 
struct A 
{ 
    static int value; 
}; 

template<class T> 
int A<T>::value = 0; 

Я специализироваться A::value на конкретный тип без проблем:

struct B 
{ 
}; 

template<> 
int A<B>::value = 1; 

Я хотел бы специализироваться A :: значение от типа шаблона, я попробовал следующее:

template<class T> 
struct C 
{ 
}; 

// error: template definition of non-template 'int A<C<T> >::value' 
template<> 
template<class T> 
int A<C<T> >::value = 2; 

есть ли способ сделать это, или это возможно только специализироваться A :: значения по типам нешаблонных?

ответ

7

Вместо введения всей явной специализации, вы могли бы просто специализировать инициализацию

template<class T> 
struct Value { 
    static int const value = 0; 
}; 

template<class T> 
struct Value< C<T> > { 
    static int const value = 2; 
}; 

template<class T> 
int A<T>::value = Value<T>::value; 
+0

+1: Возможно, вы имели в виду значение :: значение. – Chubsdad

+0

@ Chubdad - это определение OP's A :: значение. Vaue :: значение не требует определения. –

2

Вы можете использовать частичную специализацию А через C:

#include <iostream> 

using namespace std; 

template<class T> 
struct A 
{ 
    static int value; 
}; 

template<class T> 
int A<T>::value = 0; 

//(1) define the C template class first: 
template<class T> 
struct C 
{ 
}; 

//(2) then define the partial specialization of A, in terms of C: 
template<typename T> 
struct A<C<T> > 
{ 
    static int value; 
}; 

template<typename T> 
int A<C<T> >::value = 2; 

int main(void) 
{ 
    cout<<A<C<int> >::value<<endl; 

    cout<<"ok!"<<endl; 
    return 0; 
} 
+0

Это работает, но не так гибко, как ответ, который я принял. Я намерен расширить класс A для других пользовательских типов, и с этим мне нужно будет иметь все специализации A, определенные до использования A, вместо того, чтобы определять специализации Value где угодно и позволять компоновщику выполнять работу. –

+0

Хорошо, если бы я правильно понял, вы бы (по понятным причинам) не связывать специализации A с существующими определениями шаблонов и предоставлять новую специализацию каждый раз, когда вы определяете новое имя типа, например C, параметризованное аргумент шаблона. Одним из решений этого является использование частичной специализации с помощью аргумента шаблона-шаблона (см. Ниже мой второй ответ). Надеюсь, это поможет. –

0

частичной специализации с помощью шаблона аргумента шаблона (см. мой комментарий выше):

#include <iostream> 

using namespace std; 

template<class T> 
struct A 
{ 
    static int value; 
}; 

template<class T> 
int A<T>::value = 0; 



//solution 2: 
//define a template-template argument partial specialization 
//for any generic class U depending on a template argument, 
//(which is a typename, in this case, but there's no reason why 
//you wouldn't define specializations for non-types, etc.) 
//this specialization has the advantage of not depending on 
//the template definition of U (or C, etc.); in this case 
//both T and U are free to vary, with the only constraint 
//that U is parameterized by T: 
template<typename T, template<typename> class U> 
struct A<U<T> > 
{ 
    static int value; 
}; 

template<typename T, template<typename> class U> 
int A<U<T> >::value = 3; 

//define the C template class, somewhere, where/when/if needed 
//possibly in a different namespace, "module" (etc.) 
template<class T> 
struct C 
{ 
}; 

int main(void) 
{ 
    cout<<A<C<int> >::value<<endl;//this now should print out: 3 

    cout<<"ok!"<<endl; 
    return 0; 
}