2010-11-04 5 views
11

Dire che ho una classe template:Chiamare la versione non specificata di una funzione specializzandola in C++?

template <typename T> 
class foo { 
    void do_someting(T obj) { 
    // do something generic... 
    } 
}; 

e voglio specializzarmi fa_qualcosa, ma all'interno di esso voglio chiamare il "normale" funzione fai_qualcosa:

template<> 
void foo<MyObj>::do_something(MyObj obj) { 
    // do something specific... 
    // and ALSO do something generic! 
} 

c'è un modo per riferirsi alla versione normale di do_qualcosa all'interno della mia funzione specializzata? O devo solo copiare il codice?

(So che potrei refactor foo in modo tale che non avrei questo problema esatto, ma come accade non posso davvero modificare il "vero" pippo, in quanto è codice fortemente condiviso.)

+4

Non esiste una versione "normale" di "do_qualcosa" per il tipo "MyObj" - l'intero effetto della specializzazione del modello è quello di * sostituire * l'istanza che si otterrebbe dal modello base, con la classe/funzione definire nella specializzazione. –

+0

possibile duplicato di [Come posso ottenere un modello specializzato per utilizzare la versione non specificata di una funzione membro?] (Http://stackoverflow.com/questions/347096/how-can-i-get-a-specialized-template- to-use-the-unspecialized-version-of-a-member) –

+1

Giusto, ma il compilatore conosce il codice in foo :: do_qualcosa, non c'è motivo per cui non possa permettermi di fare riferimento ad esso in qualche modo. Sono assolutamente disposto a credere che questa caratteristica linguistica non esiste, però --- è quello che sto cercando di scoprire. –

risposta

7

No. La tua specializzazione è l'unica definizione che esisterà per l'argomento di tipo MyObj. Ma, considerare modificando il modello foo in questo modo, che sarà trasparente agli attuali utilizzatori del modello:

template<typename T> 
class foo { 
    void prelude(T &obj){ // choose a better name 
    /* do nothing */ 
    } 
    void do_something(T obj){ 
    prelude(obj); 
    // do something generic... 
    } 
}; 

Poi definire una specializzazione per prelude:

template<> 
void foo<MyObj>::prelude(MyObj &obj){ 
    // do something specific 
} 

Questo è simile a struttura allo main use case for private virtual members. (Si tratta di qualcosa che mi ha ispirato in questa risposta.)

+0

questo assomiglia a un'analogia del mondo modello per Sutter's NVI! –

1

Si potrebbe anche considerare un tipo che non è MyObj, ma in modo implicito si converte ad esso, ma il modo migliore sarebbe quello di refactoring e forse estrarre il qualcosa di generico comune

#include <iostream> 
#include <boost/ref.hpp> 
typedef int MyObj; 


template <typename T> 
struct foo { 
    void do_something(T obj) { 
    // do something generic... 
    std::cout << "generic " << obj << '\n'; 
    } 
}; 

template<> 
void foo<MyObj>::do_something(MyObj obj) { 
    // do something specific... 
    std::cout << "special " << obj << '\n'; 
    // and ALSO do something generic! 
    foo<boost::reference_wrapper<MyObj> >().do_something(boost::ref(obj)); 
} 

int main() 
{ 
    foo<int> f; 
    f.do_something(10); 
} 
0

Sì, questo questo è in realtà abbastanza semplice. Lasciate semplicemente che la versione generica principale della vostra funzione serva da pass-through per una funzione generica di 'implementazione' che non sia parzialmente specializzato, quindi potete semplicemente chiamarlo dalla versione specializzata della funzione iniziale come necessario .

template <typename T> 
class foo 
{ 
    void do_something(T obj) 
    { 
    do_something_impl(obj); 
    } 

    void do_something_impl(T obj) 
    { 
    // do something generic... 
    } 
}; 

Ora la specializzazione può chiamare la versione generica senza problemi:

template<> 
void foo<MyObj>::do_something(MyObj obj) 
{ 
    // do something specific... 
    do_something_impl(obj); //The generic part 
} 

penso che questo più vicino alle tue intenzioni originali di risposta di Steve M., ed è quello che faccio quando di fronte a questa edizione.

Problemi correlati