2009-10-02 14 views
10

Je me souviens quelque chose comme ceci seing se fait:Liste d'arguments de modèle de longueur variable?

template <ListOfTypenames> 
class X : public ListOfTypenames {}; 

qui est, X hérite d'une liste de longueur variable de typenames passé comme arguments de modèle. Ce code est hypothétique, bien sûr.

Je ne trouve pas de référence pour cela, cependant. C'est possible? Est-ce C++ 0x?

Répondre

23

Vous pouvez le faire dans le C++ actuel. Vous donnez le modèle un certain nombre de paramètres « assez grand », et vous leur donnez les valeurs par défaut:

class nothing1 {}; 
class nothing2 {}; 
class nothing3 {}; 

template <class T1 = nothing1, class T2 = nothing2, class T3 = nothing3> 
class X : public T1, public T2, public T3 {}; 

Ou vous pouvez obtenir plus sophistiqués et récursion utilisation. Tout d'abord vous avant-déclariez le modèle:

class nothing {}; 

template <class T1 = nothing, class T2 = nothing, class T3 = nothing> 
class X; 

Ensuite, vous vous spécialisez dans le cas où tous les paramètres sont par défaut:

template <> 
class X<nothing, nothing, nothing> {}; 

Ensuite, vous définissez correctement le modèle général (que vous avez déjà que l'avant -declared):

template <class T1, class T2, class T3> 
class X : public T1, public X<T2, T3> 

Remarquez comment dans la classe de base, vous héritez X, mais vous manquez le premier paramètre. Alors ils glissent tous le long d'un endroit. Finalement, ils seront tous par défaut, et la spécialisation interviendra, qui n'hérite de rien, mettant ainsi fin à la récursivité.

Mise à jour: juste eu un sentiment étrange que j'avais posté quelque chose comme ça avant, and guess what...

+0

vous pouvez aussi utiliser une seule classe – sellibitze

+0

@sellibitze « rien » - J'utilise utiliser une seule classe « rien » dans la version récursive. Vous ne pouvez pas utiliser la même classe pour les valeurs par défaut dans la version non récursive, car vous obtiendrez des erreurs "rien n'est déjà une classe de base directe". –

+0

Je ne comprends pas: pourquoi omettez-vous le premier paramètre en héritant de X? – Gili

19

On dirait que vous faites référence à C++ 0x Variadic Templates. Vous pouvez également obtenir le même effet en utilisant la construction TypeList d'Alexandrescu de Loki. Je crois que la syntaxe du modèle variadique en question ressemblerait à ce qui suit.

template <typename...T> 
class X : public T... {}; 
+13

Si je ne me trompe pas, vous devrez également décompresser le type: 'public T ... {};' – UncleBens

2

Le nombre variable de modèles fait partie de la prochaine norme C++. Cependant, vous pouvez en avoir un aperçu si vous utilisez GCC (à partir de la version 4.3). Voici un list of available C++0x features in GCC. Vous cherchez des modèles Variadic. Par ailleurs, si vous avez besoin d'une référence formelle sur la façon de réaliser le mécanisme d'héritage décrit par Earwicker, c'est dans le livre C++ Templates.

4

Comme d'autres ont déjà répondu, les modèles variadiques font partie de la norme suivante, mais peuvent être émulés dans le C++ actuel. Un outil pratique pour cela est d'utiliser la bibliothèque Boost.MPL. Dans votre code, vous écrivez un seul paramètre de modèle (appelons-le "Typelist"), et les utilisateurs de votre modèle enveloppent la typelist dans une séquence MPL. Exemple:

#include "YourType.h" 
#include "FooBarAndBaz.h" 
#include <boost/mpl/vector.hpp> 

YourType<boost::mpl::vector<Foo, Bar, Baz> > FooBarBaz; 

Dans la mise en œuvre de « YourType », vous pouvez accéder aux éléments Typelist avec divers métafonctions. Par exemple, at_c<Typelist, N> est l'élément N de la liste.Autre exemple, le « X » classe dans votre question pourrait être écrit avec inherit_linearly comme:

//Warning: Untested 
namespace bmpl = boost::mpl; 
template<class Typelist> 
class X : bmpl::inherit_linearly<Typelist, bmpl::inherit<bmpl::_1, bmpl::_2> >::type 
{ 
... 
};