Domanda

Sto usando libgc, un garbage collector per C e C++.Per rendere STL contenitori di immondizia da collezione, si deve utilizzare il gc_allocator.

Invece di scrivere

std::vector<MyType> 

uno deve scrivere

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

Ci potrebbe essere un modo per definire qualcosa di simile

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

Ho controllato un po ' di tempo fa e ho scoperto che non era possibile.Ma posso aver sbagliato o ci potrebbe essere un altro modo intorno.

La definizione di mappe in questo modo è particolarmente sgradevole.

std::map<Key,Val> 

diventa

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

EDIT:Dopo aver provato l'uso di macro ho trovato il seguente codice rompe:

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

La virgola all'interno dell'basato su modelli tipo di definizione è interpretato come un macro argomento separatore.

Così sembra che la classe interna/struct è la soluzione migliore.

Ecco un esempio su come sarà fatto in 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; 
È stato utile?

Soluzione

È possibile utilizzare C++11 basata su modelli di aliasing di tipo utilizzando using ad es.come questo

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

Nota:So che questa è una vecchia questione, ma dal momento che è abbastanza molti upvotes e a quanto pare nei risultati di ricerca ho pensato che meritava un aggiornamento di risposta.

Altri suggerimenti

Non è possibile utilizzare un "basato su modelli typedef", ma è possibile utilizzare una convenienza classe/struct con un interno tipo:

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

e poi utilizzare nel codice

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

E qualcosa di simile per la mappa:

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

EDIT - @Vijay:Non so se c'è un'altra possibile soluzione, che mi avrebbe fatto;una macro può darvi una notazione più compatta, ma personalmente non mi piace:

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

EDIT - @chmike:Si prega di notare che la TypeHelper soluzione non richiede di ridefinire i costruttori!

Si può pubblicamente ereditare:

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

Questo risolve il problema completamente.Il tipo derivato può essere utilizzata ovunque il tipo di base può essere utilizzato, e non c'è alcuna implementazione sovraccarico con qualsiasi compilatore decente.

Il fatto che la std::vector non distruttore virtuale potrebbe portare a comportamenti indefiniti secondo standard C++ se si tenta di eliminare una classe derivata della variabile tramite un puntatore alla classe base variabile.

Nel mondo reale questo non importa, in questo caso specifico - la classe derivata è nulla di nuovo aggiunto rispetto alla classe base e, pertanto, il distruttore della classe derivata chiama il distruttore della classe base.Procedere con la paranoia, la porta con attenzione in ogni caso.

Se non avete mai allocare variabili di classe heap (ed è tipico di allocare il vettore di variabili nello stack e come membri di altre classi) non distruttore virtuale problema non si influenzano.

Esso può essere fatto con una MACRO, se siete disposti a spingere il vostro compilatore per i suoi limiti.L'ho fatto durante l'implementazione C++ equivalenti per Java "Futuro" e "Callable" classi.La nostra libreria utilizza riferimento contati oggetti, in modo da "Riferimento<T>"è di per sé un modello di classe, dove "T" deriva da "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 bellezza di questo è che è che la Macro fa esattamente ciò che si può desiderare da un modello "typedef", i lati negativi che non è possibile utilizzare "<>" per il vostro tipo di parametro(s) e non c'è alcun tipo di inferenza.

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) { .... }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top