27 votes

typedef modèle?

Je suis en utilisant libgc, d'un ramasse-miettes pour le C et le C++. Pour faire des conteneurs STL ordures collectionner l'on doit utiliser la gc_allocator.

Au lieu d'écrire

std::vector<MyType>

on doit écrire

std::vector<MyType,gc_allocator<MyType> >

Pourrait-il y avoir un moyen de définir quelque chose comme

template<class T> typedef std::vector<T,gc_allocator<T> > gc_vector<T>;

J'ai vérifié il y a quelques temps et a découvert qu'il n'était pas possible. Mais j'ai peut-être été mal ou il y a peut-être une autre manière autour.

La définition des cartes de cette façon est particulièrement désagréable.

std::map<Key,Val>

devient

std::map<Key,Val, std::less<Key>, gc_allocator< std::pair<const Key, Val> > >

EDIT: Après essai de l'utilisation de la macro, j'ai trouvé le code suivant, il tombe:

#define gc_vector(T) std::vector<T, gc_allocator<T> >
typedef gc_vector( std::pair< int, float > ) MyVector;

La virgule à l'intérieur de l'basées sur des modèles de définition de type est interprété comme une macro argument séparateur.

Il semble donc que les inner class/struct est la meilleure solution.

Voici un exemple sur la façon dont il sera fait en C++0X

// standard vector using my allocator
template<class T>
using gc_vector = std::vector<T, gc_allocator<T> >;

// allocates elements using My_alloc
gc_vector <double> fib = { 1, 2, 3, 5, 8, 13 };

// verbose and fib are of the same type
vector<int, gc_vector <int>> verbose = fib;

33voto

Snps Points 4082

Vous pouvez utiliser l'alias de type basé sur un modèle C ++ 11 en utilisant using par exemple comme ceci

 template <typename T>
using gc_vector = std::vector<T, gc_allocator<T>>;
 

Remarque: Je sais que c'est une vieille question, mais comme elle contient de nombreux votes positifs et qu'elle apparaît dans les résultats de recherche, j'ai pensé qu'elle méritait une réponse mise à jour.

31voto

Paolo Tedesco Points 22442

Vous ne pouvez pas utiliser un "type" modèle "typedef", mais vous pouvez utiliser une commodité class/struct avec un intérieur de type:

template<typename T>
struct TypeHelper{
    typedef std::vector<T,gc_allocator<T> > Vector;
};

et puis l'utiliser dans votre code

TypeHelper<MyType>::Vector v;
TypeHelper<MyType>::Vector::iterator it;

Et quelque chose de similaire pour la carte:

template<typename K,typename V>
struct MapHelper{
    typedef std::map<K, V, gc_allocator<K,V> > Map;
};

EDIT @Vijay: je ne sais pas si il y a une autre solution possible, c'est la façon dont je le ferais; une macro pourrait vous donner une notation plus compacte, mais personnellement, je n'aime pas trop ça:

#define GCVECTOR(T) std::vector<T,gc_allocator<T> >

EDIT @chmike: Veuillez noter que l' TypeHelper solution de ne pas vous obliger à redéfinir les constructeurs!

7voto

sharptooth Points 93379

Vous pouvez publiquement hériter:

template<class T>
class gc_vector<T> : public std::vector<T, gc_allocator<T> >
{
    public:
    // You'll have to redeclare all std::vector's constructors here so that
    // they just pass arguments to corresponding constructors of std::vector
};

Cela résout votre problème complètement. Le type dérivé peut être utilisé partout où le type de base peut être utilisé, et il n'y a pas de mise en œuvre de surcharge avec n'importe quel compilateur décent.

Le fait que std::vector a non-destructeur virtuel peut conduire à un comportement indéterminé selon la norme C++ si jamais vous essayez de supprimer une classe dérivée de la variable par l'intermédiaire d'un pointeur vers la classe de base variable.

Dans le monde réel, cela ne devrait pas d'importance dans ce cas particulier, la dérivée de la classe a rien de nouveau par rapport à la classe de base et, par conséquent, le destructeur de la classe dérivée juste appelle le destructeur de la classe de base. Procéder à la paranoïa, port soigneusement de toute façon.

Si vous n'avez jamais attribuer ces variables de classe sur le tas (et c'est typique d'allouer vecteur de variables sur la pile et que les membres d'autres classes), la non-destructeur virtuel problème ne vous affecte pas.

1voto

Zack Yezek Points 41

Il peut être fait avec une MACRO, si vous êtes prêt à pousser votre compilateur à ses limites. Je l'ai fait alors que la mise en œuvre de C++ équivalents de Java "Avenir" et "Callable" des classes. Notre bibliothèque de référence-objets comptés, donc "de Référence<T>" est lui-même un modèle de classe où "T" est dérivé de "ReferencedObject".

1. Create your template Classes. Mine are:

    template<typename T>
    class Callable {
    private:

    public:
        virtual T Call() = 0;
    };

    template<typename T> CountedFuture : public ReferencedObject {
    private:
       Callable<T>* theTask;
       T            theResult;

    public:
       T Get() { 
          // Run task if necessary ...
          if(task) {
             theResult = theTask->Call();
             delete theTask;
          }
          return theResult;
       }
    };

2. In the application code I'm using references, so I define the macro:

   #define Future(T) Reference<CountedFuture<T>>

La beauté de ceci est que est que la Macro est exactement ce que vous voulez à partir d'un "modèle " typedef", les inconvénients sont que vous ne pouvez pas utiliser "<>" pour votre type de paramètre(s) et il n'y a pas d'inférence de type.

3. I can now use the Macro wherever I would use a template, like in functions:

   Future(char*) DoSomething() { ... }
   bool          TestSomething(Future(std::string) f) { .... }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X