Question

J'utilise libgc, un ramasse-miettes pour C et C ++. Pour rendre les conteneurs STL collectables, vous devez utiliser gc_allocator.

Au lieu d'écrire

std::vector<MyType> 

il faut é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 quelque temps et j'ai découvert que ce n'était pas possible. Mais j'ai peut-être eu tort ou il pourrait y avoir un autre moyen.

Définir les cartes de cette manière est particulièrement déplaisant.

std::map<Key,Val> 

devient

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

EDIT: Après avoir essayé l’utilisation de la macro, j’ai découvert que le code suivant le rompt:

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

La virgule dans la définition de type basée sur un modèle est interprétée comme un séparateur d'arguments macro.

Il semble donc que la classe / structure interne soit la meilleure solution.

Voici un exemple sur la façon de procéder 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; 
Était-ce utile?

La solution

Vous pouvez utiliser l'alias de type basé sur un modèle C ++ 11 à l'aide de using exemple. comme ça

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

Remarque: je sais que cette question est ancienne, mais comme elle a suscité beaucoup de votes positifs et que les résultats de la recherche en ont résulté, je pensais qu'elle méritait une réponse actualisée.

Autres conseils

Vous ne pouvez pas utiliser un & "; typedef basé sur un modèle &"; mais vous pouvez utiliser une classe / structure de commodité avec un type interne:

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

puis utilisez 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 s'il existe une autre solution de contournement possible, c'est ce que je ferais; une macro peut vous donner une notation plus compacte, mais personnellement, je ne l’aimerais pas:

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

EDIT - @chmike: Veuillez noter que la TypeHelper solution ne nécessite pas de redéfinir les constructeurs!

Vous pouvez hériter publiquement:

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
};

Ceci résout complètement votre problème. Le type dérivé peut être utilisé partout où le type de base peut être utilisé, et aucun compilateur décent n’impose une surcharge d’implémentation.

Le fait que std :: vector ait un destructeur non virtuel peut conduire à un comportement indéfini selon la norme C ++ si vous essayez de supprimer une variable de classe dérivée via un pointeur sur la variable de classe de base.

Dans le monde réel, cela ne devrait pas avoir d'importance dans ce cas particulier - la classe dérivée n'a rien de nouveau ajouté par rapport à la classe de base et, par conséquent, le destructeur de la classe dérivée appelle simplement le destructeur de la classe de base. Continuez avec la paranoïa, portez prudemment quand même.

Si vous n'allouez jamais ces variables de classe sur le tas (et qu'il soit typique d'affecter des variables de vecteur sur la pile et en tant que membres d'autres classes), le problème des destructeurs non virtuels ne vous concerne pas.

Cela peut être fait avec une MACRO, si vous êtes prêt à pousser votre compilateur à ses limites. Je l'ai fait en implémentant des équivalents C ++ pour le & Quot; Future & Quot; de Java. et " appelable " Des classes. Notre bibliothèque utilise des objets à comptage de références, donc & "Référence & Lt; T & Gt; &"; est lui-même une classe de modèle où " T " dérive 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 la macro fait exactement ce que vous voulez d'un & "template typedef &", les inconvénients étant que vous ne pouvez pas utiliser & "; < !> lt; > " pour votre (vos) paramètre (s) de type et il n’ya 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) { .... }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top