Utilisation des typelist en c++

Contenu du snippet

==========================
Note admin codes-sources:
==========================

ATTENTION:
Ce code est un exemple de ce qu'il est possible de faire avec des templates. Néanmoins, ce code NE doit PAS être utilisé. En effet, tous les effets que ce code émule sont disponibles dans le langage. "dynamic_cast" et "typeid" se charge déjà de le faire, et le font bien mieux.

En C++ propre, tout ce code tiendrait en 3 lignes (voir même en un mot "dynamic_cast"):

#include <iostream>

template <typename CastType, typename ObjType>
bool isInstanceOf(ObjType obj)
{
return dynamic_cast<CastType>(obj);
}

struct A {};
struct B : public A {};
struct C {};

int main()
{
A a;
B b;
C c;
C* null = 0;

std::cout << std::boolalpha
<< isInstanceOf<A*>(&a) << std::endl // true
<< isInstanceOf<A*>(&b) << std::endl // true
<< isInstanceOf<B*>(&b) << std::endl // true
<< isInstanceOf<C*>(&c) << std::endl // true
<< isInstanceOf<C*>(null) << std::endl; // false

isInstanceOf<A*>(&c); // Ne compilera pas ! Et heureusement :)

return 0;
}

==========================

Ce code permet de créer une mécanique qui imite le dynamic_cast. Le seul but est de montrer ce que l'on peut faire avec des templates.

Exemple : 'MyObject' est un objet générique, Les autres objets que l'on créera hériteront de cet objet.

MyClass1 heritera de MyObject
MyClass2 heritera de MyObject

etc, etc

Ainsi on peu générer automatiquement l'arborescence d'un objet, verifier s'il est bien une instance d'un objet parent etc etc.

Par exempl :

class MyClass1 : public MyObject
{
/* ... */
};

class MyClass2 : public MyObject
{
/* ... */
};

MyObject* obj1 = new MyClass1();
MyObject* obj2 = new MyClass2();

cout << (obj1.instanceOf<MyClass1>() ? "true" : "false") << endl; //true
cout << (obj1.instanceOf<MyClass2>() ? "true" : "false") << endl; //false
cout << (obj2.instanceOf<MyClass1>() ? "true" : "false") << endl; //true
cout << (obj2.instanceOf<MyClass2>() ? "true" : "false") << endl; //false

On peut imaginer encore plus complex

class MyClass3 : public MyClass1
{
/* ... */
};

class Myclass4 : public MyClass2
{
/* ... */
};

MyObject* obj3 = new MyClass3();
MyObject* obj4 = new MyClass4();

cout << (obj3.instanceOf<MyClass1>() ? "true" : "false") << endl; //true
cout << (obj3.instanceOf<MyClass2>() ? "true" : "false") << endl; //false
cout << (obj3.instanceOf<MyClass3>() ? "true" : "false") << endl; //true
cout << (obj3.instanceOf<MyClass4>() ? "true" : "false") << endl; //false

cout << (obj4.instanceOf<MyClass1>() ? "true" : "false") << endl; //false
cout << (obj4.instanceOf<MyClass2>() ? "true" : "false") << endl; //true
cout << (obj4.instanceOf<MyClass3>() ? "true" : "false") << endl; //false
cout << (obj4.instanceOf<MyClass4>() ? "true" : "false") << endl; //true

Voila, voir le code pour comprendre comment cela fonctionne.

Source / Exemple :


#include <string>
#include <iostream>

using namespace std;

template<class __type, class __parent>
struct TypeList
{
    typedef __type type;
    typedef __parent parent;
};

#define INTERFACE(CLASSNAME) public:\
    typedef TypeList<CLASSNAME, CLASSNAME::type> type;\
    static inline std::string ClassName()\
    {\
        return type::parent::type::ClassName()+"."#CLASSNAME;\
    }\
    virtual inline std::string className()\
    {\
        return type::parent::type::ClassName()+"."#CLASSNAME;\
    }\
    static CLASSNAME* cast(void* __object)\
    {\
        CLASSNAME* object = (CLASSNAME*)__object;\
        if(object->instanceOf<CLASSNAME>())return object;\
        else return 0;\
    }\
    private:

#define DEFINE_INTERFACE(CLASSNAME) public:\
    typedef TypeList<CLASSNAME, CLASSNAME> type;\
    static inline std::string ClassName()\
    {\
        return #CLASSNAME;\
    }\
    virtual inline std::string className()\
    {\
        return ClassName();\
    }\
    template<class __type>\
    bool instanceOf()\
    {\
        int res = className().find(__type::ClassName());\
        return res >= 0;\
    }\
    static CLASSNAME* cast(void* __object)\
    {\
        CLASSNAME* object = (CLASSNAME*)__object;\
        if(object->instanceOf<CLASSNAME>())return object;\
        else return 0;\
    }\
    private:

class MyObject
{
    DEFINE_INTERFACE(MyObject)
};

class MyClass1 : public MyObject
{
    INTERFACE(MyClass1)
};

class MyClass2 : public MyObject
{
    INTERFACE(MyClass2)
};

#define AFFICHER(X) #X" = " << X

int main(int argc, char** argv)
{
    MyObject object;
    MyClass1 class1;
    MyClass2 class2;

    cout << object.className() << endl;
    cout << class1.className() << endl;
    cout << class2.className() << endl;

    cout << endl;

    cout << AFFICHER(object.instanceOf<MyObject>()) << endl;
    cout << AFFICHER(class1.instanceOf<MyObject>()) << endl;
    cout << AFFICHER(class2.instanceOf<MyObject>()) << endl;

    cout << endl;

    cout << AFFICHER(object.instanceOf<MyClass1>()) << endl;
    cout << AFFICHER(class1.instanceOf<MyClass1>()) << endl;
    cout << AFFICHER(class2.instanceOf<MyClass1>()) << endl;

    cout << endl;

    cout << AFFICHER(object.instanceOf<MyClass2>()) << endl;
    cout << AFFICHER(class1.instanceOf<MyClass2>()) << endl;
    cout << AFFICHER(class2.instanceOf<MyClass2>()) << endl;

    cout << endl;

    cout << AFFICHER(MyObject::cast(&object)) << endl;
    cout << AFFICHER(MyClass1::cast(&object)) << endl;
    cout << AFFICHER(MyClass2::cast(&object)) << endl;

    cout << endl;

    cout << AFFICHER(MyObject::cast(&class1)) << endl;
    cout << AFFICHER(MyClass1::cast(&class1)) << endl;
    cout << AFFICHER(MyClass2::cast(&class1)) << endl;

    cout << endl;

    cout << AFFICHER(MyObject::cast(&class2)) << endl;
    cout << AFFICHER(MyClass1::cast(&class2)) << endl;
    cout << AFFICHER(MyClass2::cast(&class2)) << endl;

    return 0;
}

Conclusion :


Je pense que cela peut vous servir.

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.