5

voglio scrivere il seguente:Cosa devo fare invece della specializzazione parziale dei modelli di funzione?

template <typename S, typename T> void foo() { 
    /* code for the general case */ 
} 

template <typename T> void foo<MySType,T>() { 
    /* partially specialized code - for any kind of T, but when S is MySType */ 
} 

o, in altri casi, il seguente:

template <typename S, typename T> void bar(const S& a, const T& b) { 
    /* code for the general case */ 
} 

template <typename T> void bar<MySType,T>(const MySType& a, const T& b) { 
    /* partially specialized code - for any kind of T, but when S is MySType */ 
} 

C++ (11) non mi permette di fare questo.

Ora, ho letto this question and its answers; supponiamo di acquistare la spiegazione del motivo per cui non abbiamo una specializzazione parziale dei modelli (o presumo semplicemente che io stia vivendo nella realtà e in realtà voglia di scrivere il codice). Bene, che cosa do faccio, invece?

Preferirei non ricoprire queste funzioni in una classe a meno che non sia assolutamente la mia ultima risorsa.

+0

onestamente più mi immergo in C++ 11 e C++, in generale, più penso che "modello di specializzazione" è un titolo orribile per quello che sta succedendo . Non esiste una "specializzazione template" – user2485710

+0

@ user2485710: Mi dispiace, non capisco ... puoi elaborare? O link a dove hai discusso questo più a lungo? – einpoklum

+1

Non solo la specializzazione dei modelli è una cosa, è una macchina completa di Turing. Ti può far impazzire, però. – Potatoswatter

risposta

3

Un'altra opzione è quella di utilizzare un modello di classe di supporto, dove si può fare la specializzazione parziale e nasconderla usando una funzione wrapper, che non ha bisogno di essere in parte si è specializzata:

#include <iostream> 

template<typename S, typename T> 
struct foo_helper { 
    void foo() { 
     std::cout << "general func" << std::endl;   
    } 
}; 

struct MyType {}; 

template <typename T> 
struct foo_helper <MyType,T> { 
    void foo() { 
     std::cout << "partially specialized code - for any kind of T, but when S is MyType" << std::endl; 
    } 
}; 

template<typename S, typename T> 
void foo() { 
    foo_helper<S, T>().foo(); 
} 

int main() { 
    foo<int, int>(); 
    foo<int, double>(); 
    foo<MyType, long>(); 
} 

Questo è anche C++ 98/03 valido.

+0

Posso in qualche modo automatizzare/macroizzare l'uso della struttura di supporto? – einpoklum

5

Sovraccarico! Il sovraccarico è superiore in ogni modo alla specializzazione. Parte della risoluzione del sovraccarico sta selezionando il sovraccarico più specializzato. Basta dichiarare le "specializzazioni" come sovraccarichi e funzionerà se la specializzazione parziale dovesse avere.

Evitare argomenti modello espliciti, però. Potresti invece utilizzare l'invio di tag.

template< typename t > 
struct tag {}; 

template <typename S, typename T> foo(tag<S>, tag<T>) { 
    /* code for the general case */ 
} 

template <typename T> foo(tag<MyType>, tag<T>) { 
    /* partially specialized code - for any kind of T, but when S is MyType */ 
} 

Poiché i tag sono vuote e passato per valore, il loro contributo alla funzione di chiamata di sovraccarico possono essere eliminati dal compilatore.

+0

L'esempio dell'OP è mal costruito (tipi di reso mancanti, ecc.), Ma offre una svolta interessante. Principalmente, come sovraccarichi qualcosa che * non ha parametri *? – WhozCraig

+0

@WhozCraig Vedere l'aggiornamento – Potatoswatter

+0

+1 Stavo per suggerire di pubblicare un tag-dispatch = P – WhozCraig

2

Si potrebbe parziale specializzarsi una struttura di supporto:

#include <iostream> 

namespace Detail { 
    template <typename S, typename T> 
    struct Foo { 
     static void apply() { 
      std::cout << "general case\n"; 
     } 
    }; 
    template <typename T> 
    struct Foo<int, T> { 
     static void apply() { 
      std::cout << "specialized code\n"; 
     } 
    }; 
} 

template <typename S, typename T> 
void foo() { 
    Detail::Foo<S, T>::apply(); 
} 

int main() 
{ 
    foo<double, double>(); 
    foo<int, double>(); 
    return 0; 
} 
+0

Questo può essere automatizzato/semplificato in qualche modo, in modo che non debba scrivere sempre in modo esplicito nello spazio dei nomi, le structs et cetera? – einpoklum