Frage

Ich bin mit libgc, einen Garbage Collector für C und C ++. Um STL-Container Müllsammel machen muss den gc_allocator verwenden.

Statt des Schreibens

std::vector<MyType> 

schreiben hat

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

Gibt es einen Weg, um etwas zu definieren, wie

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

Ich habe vor einiger Zeit und fand heraus, dass es nicht möglich war. Aber ich kann falsch gewesen oder es könnte eine weitere Möglichkeit, um sein.

Definieren von Karten auf diese Weise ist besonders unangenehm.

std::map<Key,Val> 

wird

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

EDIT: Nach der Verwendung von Makro ich versucht, der folgende Code herausgefunden, bricht es:

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

Das Komma in der Templat-Typdefinition als Makro-Argument Separator interpretiert.

So scheint es, die innere Klasse / Struktur die beste Lösung ist.

Hier ist ein Beispiel dafür, wie wird es in C ++ 0X erfolgen

// 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; 
War es hilfreich?

Lösung

Sie können mit C ++ 11 Templat-Typ Aliasing mit using z.B. wie diese

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

. Hinweis: Ich weiß, das eine alte Frage, aber da es ziemlich viele upvotes und wie es in den Suchergebnissen auftaucht Ich dachte, es eine aktualisierte Antwort verdiente

Andere Tipps

Sie können keinen „Templat-typedef“, verwenden, aber Sie können eine Bequemlichkeit Klasse / Struktur mit einem inneren Typ verwenden:

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

und dann in Ihrem Code verwenden

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

Und etwas Ähnliches für die Karte:

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

EDIT - @Vijay: Ich weiß nicht, ob es eine andere mögliche Abhilfe ist, das ist, wie ich es tun würde; ein Makro können Sie eine kompaktere Notation geben, aber ich persönlich würde es nicht mögen:

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

EDIT - @chmike: Bitte beachten Sie, dass die TypeHelper Lösung nicht Sie benötigen Konstrukteure neu zu definieren

!

Sie können öffentlich erben:

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

Das löst Ihr Problem vollständig. Der abgeleitete Typ überall dort eingesetzt werden kann, wo der Basistyp verwendet werden kann, und es gibt keinen Implementierungsaufwand mit jedem anständigen Compiler.

Die Tatsache, dass std :: vector hat nicht-virtuellen Destruktor zu undefiniertem Verhalten führen könnte nach C ++ Standard, wenn Sie jemals versuchen, eine abgeleitete Klasse Variable durch einen Zeiger auf Basisklassenvariable zu löschen.

In der realen Welt solle dies nicht diesen speziellen Fall egal in - die abgeleitete Klasse hat nichts Neues hinzugefügt, verglichen mit der Basisklasse und damit der destructor für die abgeleitete Klasse nur Anrufe den destructor für die Basisklasse. Fahren Sie mit Paranoia, Port sorgfältig trotzdem.

Wenn Sie noch nie diese Klassenvariablen auf Heap reservieren (und es ist typisch Vektorvariablen auf Stapel und als Mitglieder anderer Klassen zuzuteilen) der nicht-virtuellen Destruktor Problem hat keinen Einfluss auf Sie.

Es kann mit einem MACRO getan werden, wenn Sie bereit sind, Ihre Compiler an seine Grenzen zu stoßen. Ich habe es bei der Umsetzung C ++ Äquivalente für Java „Future“ und „Callable“ Klassen. Unsere Bibliothek verwendet Referenz-Objekte gezählt, so „Referenz “ selbst ist eine Template-Klasse, wo „T“ leitet sich von „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>>

Das Schöne daran ist, dass ist, dass das Makro genau das tut, was man von einem „Template typedef“ wollen würde, wobei die Nachteile, dass Sie nicht „<>“ für die Typ-Parameter verwenden können (n), und es gibt keine Typinferenz.

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) { .... }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top