2009-11-25 21 views
9

voglio specializzare un modello di classe con la seguente funzione:la specializzazione del modello con un tipo di templatized

template <typename T> 
class Foo 
{ 
public: 
    static int bar(); 
}; 

La funzione non ha argomenti e deve restituire un risultato in base al tipo di Foo. (In questo esempio giocattolo, torniamo il numero di byte del tipo, ma alla effettiva applicazione vogliamo tornare qualche oggetto meta-dati.) La specializzazione funziona per i tipi completamente specificati:

// specialization 1: works 
template <> 
int Foo<int>::bar() { return 4; } 

// specialization 2: works 
template <> 
int Foo<double>::bar() { return 8; } 

// specialization 3: works 
typedef pair<int, int> IntPair; 
template <> 
int Foo<IntPair>::bar() { return 2 * Foo<int>::bar(); } 

Tuttavia, Vorrei generalizzare questo ai tipi che dipendono da (altri) parametri del modello stessi. L'aggiunta dei seguenti specializzazione dà un errore di compilazione (VS2005):

// specialization 4: ERROR! 
template <> 
template <typename U, typename V> 
int Foo<std::pair<U, V> >::bar() { return Foo<U>::bar() + Foo<V>::bar(); } 

Io parto dal presupposto che non è legale C++, ma perché? E c'è un modo per implementare questo tipo di schema elegantemente?

+1

Si noti, tuttavia, che non è necessario alcun specializzazioni per la restituzione delle dimensioni di T : 'static int Foo() {return sizeof (T); } '. Mi chiedo se questo tipo di schema potrebbe non essere d'aiuto con il tuo vero problema. – UncleBens

risposta

7

specializzazione Partitial è valida solo per le classi, non funzioni.

Soluzione:

template <typename U, typename V> 
class Foo<std::pair<U, V> > { 
public: 
static int bar() { return Foo<U>::bar() + Foo<V>::bar(); } 
}; 

Se non si desidera specializzarsi pienamente classe, utilizzare struct ausiliario

template<class T> 
struct aux { 
    static int bar(); 
}; 

template <>int aux <int>::bar() { return 4; } 
template <>int aux <double>::bar() { return 8; } 

template <typename U, typename V> 
struct aux <std::pair<U, V> > { 
    static int bar() { return Foo<U>::bar() + Foo<V>::bar(); } 
}; 

template<class T> 
class Foo : aux<T> { 
    // ... 
}; 
+1

Nell'esempio tutte le specializzazioni sono specializzazioni di classe – TimW

+1

Sì. destra. La funzione di specializzazione partitial è proibita. È possibile creare la classe base solo per la barra delle funzioni. –

+0

@TimW, nella domanda, il trucco è che la classe non è specializzata.Questo è fuori dallo standard: "Una funzione membro, una classe membro o un membro dati statici di un modello di classe può essere esplicitamente specializzata per una specializzazione di classe che è implicitamente istanziata; Se tale specializzazione esplicita per il membro di un modello di classe una funzione membro speciale implicitamente dichiarata (clausola 12), il programma è mal formato. ". È una specializzazione per una determinata istanza implicita (quindi, nessuna dipendenza parametro-parametro) di quel modello (non per alcuna specializzazione parziale). –

5

È perfettamente legale in C++, è la specializzazione di modelli parziali.
Rimuovere il template <> e se non lo fa già esiste aggiungere l'esplicito modello di classe di specializzazione e dovrebbe compilare su VS2005 (ma non in VC6)

// explicit class template specialization 
template <typename U, typename V> 
class Foo<std::pair<U, V> > 
{ 
public: 
    static int bar(); 
}; 

template <typename U, typename V> 
int Foo<std::pair<U, V> >::bar() { return Foo<U>::bar() + Foo<V>::bar(); } 
+1

@litb Finora posso vedere tutte le sue funzioni sono specializzazioni di classe. Non vedo alcun modello di funzione, vero? – TimW

+0

@TimW: quando si dichiara un modello di classe, ogni funzione membro è un modello di funzione indipendente. L'OP sta cercando di specializzare un modello di funzione membro senza specializzare l'intero modello di classe. Questo è il punto. Tuttavia, la specializzazione parziale non è supportata per i modelli di funzione. Questo è il problema. – AnT

+0

@TimW, non esiste un modello di funzione. Ma non esiste anche una specializzazione specifica per i modelli di classe. Vedi sopra per la quotazione standard: questo è un caso speciale nello standard e consente di specializzare esplicitamente membri non appartenenti a modelli separati di modelli di classe, senza specializzare esplicitamente l'intero modello di classe. Funziona nominando una determinata istanza implicita (nel suo esempio, ad esempio 'Foo ' o 'Foo ') che in assenza di specializzazioni parziali di' Foo' selezionerà il modello primario e specializzerà il membro 'bar' di esso. –

Problemi correlati