2009-04-28 5 views
27

Parfois, il fonctionne parfois:Lorsqu'un compilateur peut déduire un paramètre de modèle?

template <class T> 
void f(T t) {} 

template <class T> 
class MyClass { 
public: 
    MyClass(T t) {} 
}; 

void test() { 
    f<int>(5); 
    MyClass<int> mc(5); 
    f(5); 
    MyClass mc(5); // this doesn't work 
} 

est-il un moyen de pirater autour de l'exemple ci-dessus? C'est à dire. forcez le compilateur à déduire le paramètre de modèle du paramètre constructeur.

Cela sera-t-il corrigé à l'avenir ou y a-t-il une bonne raison de ne pas le faire?

Quelle est la règle générale lorsque le compilateur peut déduire un paramètre de modèle?

Répondre

47

paramètres du modèle peuvent être inférées pour modèles de fonction lorsque le type de paramètre peut être déduit à partir des paramètres modèle

On peut donc conclure ici:

template <typename T> 
void f(T t); 

template <typename T> 
void f(std::vector<T> v); 

mais pas ici:

template <typename T> 
T f() { 
    return T(); 
} 

Et non dans modèles de classe.

Donc, la solution habituelle à votre problème est de créer une fonction enveloppe, similaire à la fonction de la bibliothèque standard std::make_pair:

template <class T> 
    class MyClass { 
    public: 
     MyClass(T t) {} 
     void print(){ 
      std::cout<<"try MyClass"<<std::endl; 
     } 
    }; 

    template <typename T> 
    MyClass<T> MakeMyClass(T t) { return MyClass<T>(t); } 

puis appelez auto a = MakeMyClass(5); instancier la classe.

+0

+1, approfondie. Minor nit: Je suggère de changer "quand le type de paramètre dépend" à "quand un type de paramètre est dépendant". –

+2

void f (nom de fichier T :: const_iterator t); << ici, T apparaît dans un contexte inductible. même en l'appelant avec un vecteur :: const_iterator, par exemple, il ne sera pas en mesure de déduire le vecteur pour T. la raison en est que la signification de :: const_iterator dépend de T. mais T dépend à nouveau de la signification de :: const_iterator. C'est pourquoi boost :: implicit_cast est codé comme ceci: template T implicit_cast (typename identity :: type t) {return t; } Là encore, nous avons un contexte inductible. –

+0

Standard-ref est 14.8.2.4/4 (le dernier projet de C++ 1x le situe à 14.9.2.5/5 - corrigeant également quelques-uns des défauts du libellé de la norme actuelle). :) Bravo –

Questions connexes