Question

Je l'ai lu dans TypeListes « Modern C ++ Design » et je l'ai compris comme une sorte d'union pour les types. En mettant diffrent, les types non apparentés dans un typelist, on peut l'utiliser pour représenter plus d'un type à la fois, sans héritage. Je l'ai testé typelist dans certaines fonctions simples avec des types primitifs, mais je ne pouvais pas l'un d'eux pour travailler.

Quelqu'un pourrait-il me dire si mon unterstanding de TypeListes est juste et donner un exemple du monde réel simple, comment utiliser TypeListes chaque jour le code moyen? Merci à l'avance.

BTW, j'utilise Windows et Visual Studio 2005 et son compilateur.

EDIT: mes exemples sont partis, j'utilise un projet de bac à sable vs pour tester ces choses. Mais il était calme semblable au code dans le tutoriel Dobbs:

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

Cela fonctionne, mais je ne vois pas l'avantage sur l'héritage qui est capable de faire la même chose. Et casting dynamique ne fonctionnent pas sur les types primitifs. Est-il possible de l'utiliser comme une valeur de retour comme:

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

    return "five";
}
Était-ce utile?

La solution

Les TypeListes sont des collections de compilation génériques de types. Si vous utilisez dynamic_cast, il vous manque le point, car il ne devrait pas être nécessaire, car il est statique, compilation concept de temps.

  

Cela fonctionne, mais je ne vois pas l'avantage sur l'héritage qui est capable de faire la même chose.

Vous ne pouvez pas faire une Hériter de type existant de tout ce que vous voulez. Ceci est tout simplement pas possible, parce que ce type existant peut être construit dans le type ou un type dans une bibliothèque. Pensez aux TypeListes comme des extensions des listes de types (par exemple dans std :: paire) pour un nombre raisonnable de types (au lieu de seulement 2).

Les TypeListes peuvent être utilisés pour créer une installation pour passer autour d'un ensemble d'arguments à une fonction. Ceci est un morceau de code qui appelle functors généralisées de 5 paramètres (un autre notion de Modern C ++ conception) avec les paramètres fournis dans un tupe (encore une autre) avec l'typelist qui définit les types d'objets contenus dans le tuple:

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

Notez que seulement avec d'autres concepts tels que tuples ou les foncteurs TypeListes commencent à être utile. De plus, je suis EPROUVE Loki pendant environ 2 ans dans un projet et à cause du code du modèle (beaucoup de celui-ci) la taille des exécutables dans les versions de DEBUG ont tendance à être BIG (mon dossier est de 35 Mo environ). De plus il y avait un peu de succès sur la vitesse de compilation. Rappelez-vous également que C ++ 0x va probablement inclure un mécanisme équivalent. Conclusion:. Essayez de ne pas utiliser TypeListes si vous n'avez pas

Autres conseils

TypeListes sont une façon de passer « listes de paramètres » à le modèle méta programmes « Execute » dans le cadre du processus de compilation.

En tant que tel, ils peuvent être utilisés pour générer une sorte de type « union », mais cela est une seule utilisation possible.

Pour un exemple du « monde réel »: Nous avons utilisé TypeListes comme un moyen de générer la méthode « QueryInterface » automatiquement lors de la mise en œuvre des objets COM dans la section la bibliothèque de la comète.

Il vous permet d'écrire du code comme ceci:

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

Dans cet exemple, « make_list » était un modèle utilisé pour générer une « liste de type » que le modèle implement_qi pourrait alors « énumérer sur » générer le code QueryInterface approprié .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top