web-dev-qa-db-fra.com

Stockage d'un type en C ++

Est-il possible de stocker un nom de type en tant que variable C++? Par exemple, comme ceci:

type my_type = int; // or string, or Foo, or any other type
void* data = ...;
my_type* a = (my_type*) data;

Je sais que 99,9% du temps, il y a une meilleure façon de faire ce que vous voulez sans avoir recours à des pointeurs vides, mais je suis curieux de savoir si C++ permet ce genre de chose.

31
perimosocordiae

Non, ce n'est pas possible en C++.

L'opérateur RTTI typeid vous permet d'obtenir des informations sur les types lors de l'exécution: vous pouvez obtenir le nom du type et vérifier s'il est égal à un autre type, mais c'est tout.

23
Thomas

Pas comme écrit, mais vous pourriez faire quelque chose de similaire ...

class Type
{
    public:
        virtual ~Type(){}
        virtual void* allocate()const=0;
        virtual void* cast(void* obj)const=0;
};

template<typename T> class TypeImpl : public Type
{
      public:
         virtual void* allocate()const{ return new T; }
         virtual void* cast(void* obj)const{ return static_cast<T*>(obj); }
};

// ...
Type* type = new TypeImpl<int>;
void* myint = type->allocate();
// ...

Ce genre de chose peut être étendu en fonction des fonctionnalités dont vous avez besoin.

16

Vous ne pouvez pas faire cela en C++, mais vous pouvez utiliser le boost n'importe quelle bibliothèque puis tester le type qu'elle contient. Exemple:

bool is_int(const boost::any & operand)
{
  return operand.type() == typeid(int);
}

http://www.boost.org/doc/libs/1_42_0/doc/html/any/s02.html

9
Chris H

Non, vous ne pouvez pas stocker le type directement comme vous le souhaitez, mais vous pouvez enregistrer le nom du type à la place.

const char* str = typeid(int).name();

Je suppose que chaque fois que vous envisagez d'utiliser cette variable pour la comparaison, vous pouvez à la place comparer la variable str à la fonction name() des types.

const char* myType = typeid(int).name();

//....

//Some time later:
if(!strcmp(myType, typeid(int).name()))
{
  //Do something
}

Plus d'informations disponibles ici

6
Brian R. Bondy

Oui, si vous le codez vous-même.

enum Foo_Type{
    AFOO,
    B_AFOO,
    C_AFOO,
    RUN
};

struct MyFoo{
    Foo_Type m_type;
    Boost::shared_ptr<Foo> m_foo;
}

comme indiqué ci-dessous, ce que j'ai omis, c'est que tous ces types de "foo" devraient être liés à Foo. Foo serait essentiellement votre interface.

3
wheaties

Aujourd'hui, j'ai eu un problème similaire lors du codage:
. J'ai besoin d'une solution qui ne transforme pas la variable explicitement parce que je dois réduire la quantité de code.

Ma solution (mais je ne l'ai pas encore testée) ressemble à une réponse précédente. En fait, c'est une solution tout à fait expérimentale. Ça ressemble à ça ...

// interface to use in the function

class Type   
{
public:
    virtual void* getObj()const=0;
};

// here the static_cast with the "stored" type

template<typename T> class TypeImpl : public Type
{
public:
    TypeImpl(T *obj) {myobj=obj;}
    virtual void* getObj()const{ return static_cast<T*>(myobj); }

private: 
    T* myobj;
};

// here the type that will contain the polimorific type
// that I don't want to cast explicitly in my code
Type *refobj;

// here the "user code "
void userofTypes()
{
    ( refobj->getObj() ).c_str(); 
    // getObj() should return a string type over which
    // calling string concrete functions ...let's try!
}

void main()
{
    refobj=new TypeImpl < string > ( new string("hello") );
    userofTypes();
}
// it might seem absurd don't cast refobj explicitly, but of
// course there are situation in which it can be useful!
2
David

Les types ne sont pas des objets en C++ (où ils sont en Ruby, par exemple), vous ne pouvez donc pas stocker les instances d'un type. En fait, les types n'apparaissent jamais dans le code d'exécution (RTTI est juste un stockage supplémentaire).

Sur la base de votre exemple, il semble que vous recherchiez des typedefs.

typedef int Number;
Number one = 1;
Number* best = (Number*) one;

Notez qu'un typedef n'est pas stockage le type; c'est aliasing le type.

1
Andres Jaan Tack

Un meilleur processus consiste à avoir une classe de base commune contenant une méthode de chargement et une interface pour chargeurs. Cela permettrait à d'autres parties du programme de charger des données de manière générique sans connaître la classe descendante:

struct Load_Interface;

struct Loader
{
  virtual void visit(Load_Interface&) = 0;
}

struct Load_Interface
{
  virtual void accept_loader(Loader& l)
    {
        l.visit(*this);
    }
};

Cette conception évite d'avoir à connaître les types d'objets.

1
Thomas Matthews