2009-08-23 23 views
7

voglio specializzarmi seguente funzione membro:template specializzazione della classe template

class foo { 
    template<typename T> 
    T get() const; 
}; 

Per altra classe bar che dipende da modelli pure.

Per esempio, vorrei bar essere std::pair con alcuni parametri di modello, qualcosa di simile:

template<> 
std::pair<T1,T2> foo::get() const 
{ 
    T1 x=...; 
    T2 y=...; 
    return std::pair<T1,T2>(x,y); 
} 

Dove T1 e T2 sono modelli pure. Come si può fare? Per quanto ne so dovrebbe essere possibile.

Così ora posso chiamare:

some_foo.get<std::pair<int,double> >(); 

La piena risposta definitiva /:

template<typename T> struct traits; 
class foo { 
    template<typename T> 
    T get() const 
    { 
     return traits<T>::get(*this); 
    } 
}; 

template<typename T> 
struct traits { 
    static T get(foo &f) 
    { 
     return f.get<T>(); 
    } 
}; 

template<typename T1,typename T2> 
struct traits<std::pair<T1,T2> > { 
     static std::pair<T1,T2> get(foo &f) 
     { 
       T1 x=...; 
       T2 y=...; 
       return std::make_pair(x,y); 
     } 
}; 
+0

Non è chiaro cosa intendi. Vuoi una specializzazione che si applica ogni volta che T1 e T2 sono modelli? O quando sono un modello specifico? O quando sono modelli, e il loro parametro è di alcuni tipi specifici? – jalf

+0

Voglio dire, che voglio specializzare la mia funzione per un altro tipo specifico (come std :: pair) che ha bisogno anche di alcuni parametri del template. – Artyom

+0

Si prega di controllare questo: http://stackoverflow.com/questions/947943/template-specialisation-where-templated-type-is-also-a-plate –

risposta

8

Non si può in parte specializzarsi modelli di funzione, scusate ma queste sono le regole. Si può fare qualcosa di simile:

class foo { 
    ... 
}; 


template<typename T> 
struct getter { 
    static T get(const foo& some_foo); 
}; 

template<typename T1, typename T2> 
struct getter< std::pair<T1, T2> > { 
static std::pair<T1, T2> get(const foo& some_foo) { 
    T1 t1 = ...; 
    T2 t2 = ...; 
    return std::make_pair(t1, t2); 
}; 

e poi chiamarlo come

getter<std::pair<int, double> >::get(some_foo); 

però. Potrebbe essere necessario fare un po 'di scherzi con friend nave o visibilità se get davvero bisogno di essere una funzione membro.

Elaborare su suggerimento di SBI:

class foo { 
    ... 
    template<typename T> 
    T get() const; 
}; 

template<typename T> 
T foo::get() const 
{ 
    return getter<T>::get(*this); 
    /*   ^-- specialization happens here */ 
} 

E ora sei tornato ad essere in grado di dire

std::pair<int,double> p = some_foo.get<std::pair<int, double> >(); 
+1

Si potrebbe. tuttavia, rendere 'getter' un membro (prossimamente' privato') della classe e farlo chiamare tramite un normale template di funzione membro. In questo modo, gli utenti della tua classe non devono preoccuparsi di questo meccanismo. – sbi

+0

@sbi, questo è un grande punto. –

1

Hai bisogno di sovraccaricare la funzione di membro per la coppia, come in

template <T, V> std::pair<T, V> foo::get() 

Nel caso generale sarà necessario essere in grado di disambiguare tra i vari sovraccarichi. Nel caso la disambiguazione è facile perché la coppia è basata su due tipi di modelli mentre il membro originale era basato su T solo su modelli.

Se invece è necessaria una specializzazione per, ad esempio, std :: vector, ovvero per un contenitore con un modello di parametro singolo, è necessario fare attenzione poiché dato che può essere fonte di confusione per il compilatore capire se si desidera istanziare la specializzazione modello in cui il modello T è std :: vector o la specializzazione per il sovraccarico,

template <T> std::<vector <T> foo::get() const 

la sintassi prevista non può funzionare in quanto si sta specializzando completamente la funzione di membro,

template <>,

ma si stanno tralasciando due tipi non specificati, T1 e T2.

+0

Questo non funziona: "prototipo per' std :: pair <_T1, _T2> foo :: get() 'non corrisponde a nessuno nella classe' foo'; candidato è: modello T foo :: get() " – Artyom

+0

si dovrebbe dichiarare in classe foo 'template std :: coppia get) const (;' e quindi chiamare qualcosa come: 'std :: coppia p_int = f.get (); ' – Francesco

Problemi correlati