2017-10-02 2 views
1

Je voudrais spécialiser une fonction en utilisant un type de modèle mais j'ai de la difficulté à obtenir les résultats désirés.Comment se spécialiser pour les arguments de modèle de modèle

Prenons l'exemple simple suivant

#include <iostream> 
#include <typeinfo> 
#include <vector> 


template <typename T> 
void foo(){ 
    std::cout << "In foo1 with type: " << typeid(T).name() << std::endl; 
} 

template< template<class, class...> class VEC, typename T> 
void foo(){ 
    std::cout << "In foo2 with vec type: " << typeid(VEC<T>).name() 
       << " and template type: " << typeid(T).name() << std::endl; 
} 


int main() { 
    foo<int>(); 
    foo<std::vector, int>(); 
    foo<std::vector<int>>(); // Would like this to call the second version of foo 
} 

La sortie est

In foo1 with type: i 
In foo2 with vec type: St6vectorIiSaIiEE and template type: i 
In foo1 with type: St6vectorIiSaIiEE 

Est-il possible d'écrire une signature de modèle pour la deuxième version de foo qui serait utilisé pour la dernière invocation de foo (avec le paramètre template std :: vector)?

Merci!

+0

Souhaitez-vous: 'template <> void foo >() { std :: cout << "En foo1 spécialisé avec type vec:" << typeid (VEC ) .name() << "et type de template:" < Jarod42

+0

@ Jarod42 Je veux quelque chose de plus général que cela – acorso

Répondre

1

Puisque vous ne pouvez pas spécialiser les modèles de fonction partiellement, l'approche habituelle est d'utiliser un modèle de classe d'aide:

template <typename T> struct X 
{ 
    static void f() { std::cout << "Primary\n"; } 
}; 

template <template <typename...> class Tmpl, typename T> 
struct X<Tmpl<T>> 
{ 
    static void f() { std::cout << "Specialized\n"; } 
}; 

template <typename T> void foo() { X<T>::f(); } 
+0

[Démo] (https://wandbox.org/permlink/0XiP7CcuI09qaxA4) –

+0

C'est ce que je cherchais. Merci! – acorso

+0

@acorso: Pas de problème :-) –

0

Une alternative est dispatching tag:

template <typename> struct Tag{}; 

template <typename T> void foo(Tag<T>) { std::cout << "generic\n"; } 

template <typename T> void foo(Tag<std::vector<T>>) { std::cout << "vector\n"; } 


template <typename T> void foo() 
{ 
    foo(Tag<T>{}); 
}