2010-10-16 4 views
6

sagen, dass ich die folgende Klasse haben:Wie spezialisiere ich ein statisches Mitglied einer Template-Klasse auf einem Template-Typ?

struct B 
{ 
}; 

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

Ich möchte spezialisieren A :: Wert auf eine Vorlagentyp, I:

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

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

I A::value auf konkreter ohne Probleme spezialisieren folgendes versucht:

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; 

gibt es eine Möglichkeit, dies zu tun, oder ist es nur möglich, einen :: Wert auf nicht-Template-Typen zu spezialisieren?

Antwort

7

Statt eine ganze explizite Spezialisierung einzuführen, könnten Sie spezialisieren sich nur die Initialisierung

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: können Sie Wertsein:: Wert. – Chubsdad

+0

@Chubsdad es ist eine Definition der OP A :: Wert. Vaue :: Wert benötigt keine Definition. –

2

Sie partielle Spezialisierung von A über C verwenden können:

#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

Das funktioniert, ist aber nicht so flexibel wie die Antwort, die ich angenommen habe. Ich beabsichtige, Klasse A für andere benutzerdefinierte Typen zu erweitern, und damit müsste ich alle Spezialisierungen von A definiert haben, bevor ich A benutze, anstatt in der Lage zu sein, Spezialisierungen von Value irgendwo zu definieren und den Linker die Arbeit machen zu lassen. –

+0

Ok, wenn ich deinen Punkt richtig verstanden habe, würdest du (verständlicherweise) die Spezialisierungen von A nicht an bereits existierende Vorlagendefinitionen binden und jedes Mal eine neue Spezialisierung anbieten, wenn du einen neuen Typnamen wie C definierst ein Vorlagenargument Eine Lösung dafür ist die teilweise Spezialisierung über ein Template-Template-Argument (siehe unten meine 2. Antwort). Ich hoffe, das hilft. –

0

Teil Spezialisierung über eine Template-Template-Argument (siehe mein Kommentar oben):

#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; 
} 
Verwandte Themen