2008-10-17 11 views
167

J'ai vu quelques exemples de C++ en utilisant des paramètres de modèle de modèle (c'est-à-dire des modèles qui prennent des modèles en tant que paramètres) pour faire une conception de classe basée sur des règles. Quels autres usages cette technique a-t-elle?Quelles sont les utilisations des paramètres de modèle de modèle en C++?

+4

Je suis venu de l'autre direction (FP, Haskell, etc.) et j'ai atterri dessus: http://stackoverflow.com/questions/2565097/higher-kinded-types-with-c –

Répondre

138

Je pense que vous devez utiliser la syntaxe de modèle modèle pour passer un paramètre dont le type est un modèle dépendant d'un autre modèle comme celui-ci:

template <template<class> class H, class S> 
void f(const H<S> &value) { 
} 

Ici, H est un modèle, mais je voulais cette fonction pour traiter avec toutes les spécialisations de H.

NOTE: J'ai programmé C++ pendant de nombreuses années et j'en avais seulement besoin une fois. Je trouve que c'est une fonctionnalité rarement nécessaire (bien sûr quand vous en avez besoin!).

J'ai essayé de penser à de bons exemples, et pour être honnête, la plupart du temps ce n'est pas nécessaire, mais imaginons un exemple. Faisons semblant que std::vectorn'a pas ont un typedef value_type.

Alors, comment écrire une fonction qui peut créer des variables de type correct pour les éléments de vecteurs? Cela fonctionnerait.

template <template<class, class> class V, class T, class A> 
void f(V<T, A> &v) { 
    // This can be "typename V<T, A>::value_type", 
    // but we are pretending we don't have it 

    T temp = v.back(); 
    v.pop_back(); 
    // Do some work on temp 

    std::cout << temp << std::endl; 
} 

NOTE: nous std::vector a deux paramètres de modèle, le type et allocateur, donc nous avons dû accepter les deux. Heureusement, à cause de la déduction de type, nous n'aurons pas besoin d'écrire explicitement le type exact.

que vous pouvez utiliser comme ceci:

f<std::vector, int>(v); // v is of type std::vector<int> using any allocator 

ou mieux encore, nous pouvons simplement utiliser:

f(v); // everything is deduced, f can deal with a vector of any type! 

MISE À JOUR: Même cet exemple artificiel, tout en illustration, n'est plus une exemple étonnant en raison de C++ 11 présentant auto. Maintenant, la même fonction peut être écrite comme:

template <class Cont> 
void f(Cont &v) { 

    auto temp = v.back(); 
    v.pop_back(); 
    // Do some work on temp 

    std::cout << temp << std::endl; 
} 

comment je préférerais écrire ce type de code.

+1

Si f est une fonction définie par le l'utilisateur d'une bibliothèque, il est moche que l'utilisateur doit passer std :: allocator comme argument. Je m'attendais à ce que la version sans l'argument std :: allocator ait fonctionné en utilisant le paramètre par défaut de std :: vector. Y a-t-il des mises à jour sur ce point C++ 0x? –

+0

Eh bien, vous n'avez pas à fournir l'allocateur. Ce qui est important, c'est que le paramètre du modèle de template a été défini sur le nombre correct d'arguments. Mais la fonction ne devrait pas se soucier de leurs "types" ou de leur signification, ce qui fonctionne bien en C++ 98: 'template