So verwenden Sie Typlisten

Lesezeit: 5 Minuten

So verwenden Sie Typlisten
DaClown

Ich habe im ‘Modern C++ Design’ über Typlisten gelesen und sie als eine Art Union für Typen verstanden. Indem man verschiedene, nicht verwandte Typen in eine Typliste einfügt, kann man sie verwenden, um mehr als einen Typ gleichzeitig ohne Vererbung darzustellen. Ich habe typelist in einigen einfachen Funktionen mit primitiven Typen getestet, aber ich konnte keine davon zum Laufen bringen.

Könnte mir jemand sagen, ob mein Verständnis von Typlisten richtig ist, und ein einfaches Beispiel aus der Praxis geben, wie man Typlisten in alltäglichem durchschnittlichem Code verwendet? Vielen Dank im Voraus.

Übrigens verwende ich Windows und Visual Studio 2005 und seinen Compiler.

BEARBEITEN: Meine Beispiele sind weg, ich verwende ein Sandbox-Projekt in vs, um diese Dinge zu testen. Aber es war dem Code im Dobbs-Tutorial ziemlich ähnlich:

void SomeOperation(DocumentItem* p)
{
    if (TextArea* pTextArea = dynamic_cast<TextArea*>(p))
    {
        ... operate on a TextArea object ...
    }
    else if (VectorGraphics* pVectorGraphics =
        dynamic_cast<VectorGraphics*>(p))
    {
        ... operate on a VectorGraphics object ...
    }
    else if (Bitmap* pBitmap = dynamic_cast<Bitmap*>(p))
    {
        ... operate on a Bitmap object ...
    }
    else
    {
        throw "Unknown type passed";
    }
}

Dies funktioniert, aber ich sehe nicht den Vorteil gegenüber der Vererbung, die in der Lage ist, dasselbe zu tun. Und die dynamische Besetzung funktioniert nicht bei primitiven Typen. Ist es möglich, es als Rückgabewert zu verwenden, wie:

typedef Typelist<int, string> mylist
mylist myfunction() {
    if(foo == bar)
        return 5;

    return "five";
}

  • Fügen Sie Ihrer Frage ein Beispiel für den Code hinzu, der nicht funktioniert hat.

    anon

    23. Mai ’09 um 16:54 Uhr

So verwenden Sie Typlisten
poliklosio

Die Typlisten sind generische Sammlungen von Typen zur Kompilierzeit. Wenn Sie dynamic_cast verwenden, verpassen Sie den Punkt, da es nicht benötigt werden sollte, da es sich um ein statisches Konzept zur Kompilierzeit handelt.

Dies funktioniert, aber ich sehe nicht den Vorteil gegenüber der Vererbung, die in der Lage ist, dasselbe zu tun.

Sie können nicht festlegen, dass ein vorhandener Typ von allem erbt, was Sie möchten. Dies ist einfach nicht machbar, da dieser vorhandene Typ ein eingebauter Typ oder ein Typ aus einer Bibliothek sein kann. Stellen Sie sich die Typlisten als Erweiterungen von Typenlisten (zB in std::pair) für eine vernünftige Anzahl von Typen (statt nur 2) vor.

Die Typlisten können verwendet werden, um eine Einrichtung zu erstellen, um einen Satz von Argumenten an eine Funktion weiterzugeben. Dies ist ein Codestück, das verallgemeinerte Funktoren von 5 Parametern (ein weiteres Konzept aus dem modernen C++-Design) mit den Argumenten aufruft, die in einem Tupe (noch einem anderen) mit der Typliste bereitgestellt werden, die Typen von Objekten definiert, die im Tupel enthalten sind:

//functor is just a holder of a pointer to method and a pointer to object to call this 
//method on; (in case you are unfamiliar with a concept)
template<class R, class t0, class t1, class t2, class t3, class t4>
R call(Loki::Functor<R,LOKI_TYPELIST_5(t0, t1, t2, t3, t4
    )> func,
    Loki::Tuple<LOKI_TYPELIST_5(t0, t1, t2, t3, t4)> tuple)
{
    ///note how you access fields
    return func(Loki::Field<0>(tuple), Loki::Field<1>(tuple),
        Loki::Field<2>(tuple), Loki::Field<3>(tuple),
        Loki::Field<4>(tuple));
}

//this uses the example code
#include<iostream>
using namespace std;

int foo(ostream* c,int h,float z, string s,int g)
{
    (*c)<<h<<z<<s<<g<<endl;
    return h+1
}

int main(int argc,char**argv)
{
    Loki::Functor<int,LOKI_TYPELIST_5(ostream*, int, float, string, int)> f=foo;
    //(...)
    //pass functor f around
    //(...)
    //create a set of arguments
    Loki::Tuple<LOKI_TYPELIST_5(ostream*, int, float, string, int)> tu;
    Field<0>(tu)=&cout;
    Field<1>(tu)=5;
    Field<2>(tu)=0.9;
    Field<3>(tu)=string("blahblah");
    Field<4>(tu)=77;
    //(...)
    //pass tuple tu around, possibly save it in a data structure or make many 
    //specialized copies of it, or just create a memento of a call, such that 
    //you can make "undo" in your application; note that without the typelist 
    //you would need to create a struct type to store any set of arguments;
    //(...)
    //call functor f with the tuple tu
    call(f,tu);
}

Beachten Sie, dass die Typlisten erst bei anderen Konzepten wie Tupeln oder Funktoren nützlich sind. Außerdem habe ich Loki seit ungefähr 2 Jahren in einem Projekt erlebt und aufgrund des Vorlagencodes (viel davon) sind die Größen der ausführbaren Dateien in DEBUG-Versionen tendenziell GROSS (mein Rekord war 35 MB oder so). Auch bei der Geschwindigkeit der Kompilierung gab es einen kleinen Hit. Denken Sie auch daran, dass C++0x wahrscheinlich einen äquivalenten Mechanismus enthalten wird. Fazit: Versuchen Sie, keine Typlisten zu verwenden, wenn Sie es nicht müssen.

  • Vielen Dank, Sie haben einiges für mich geklärt. Ich denke, ich sollte das Kapitel noch einmal lesen.

    – DaClown

    24. Mai ’09 um 7:55

Typlisten sind eine Möglichkeit, “Parameterlisten” an Template-Metaprogramme zu übergeben, die als Teil des Kompilierungsprozesses “ausgeführt” werden.

Als solche können sie verwendet werden, um eine Art “Union”-Typ zu generieren, aber dies ist nur eine mögliche Verwendung.

Für ein “reales” Beispiel: Wir haben Typlisten verwendet, um die Methode “QueryInterface” automatisch zu generieren, wenn COM-Objekte in der Komet Bücherei.

Es ermöglichte Ihnen, Code wie diesen zu schreiben:

class Dog : public implement_qi<make_list<IAnimal, INoisy, IPersistStream> >
{
    // The implement_qi template has provided
    // an implementation of COM's QueryInterface method for us without
    // having to write an ugly ATL "message map" or use any Macros.
    ...
}

In diesem Beispiel war “make_list” eine Vorlage, die verwendet wurde, um eine “Typenliste” zu generieren, die die Vorlage implement_qi dann “aufzählen” konnte Generieren Sie den entsprechenden QueryInterface-Code.

.

228150cookie-checkSo verwenden Sie Typlisten

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy