开发者

Storing a type in C++

开发者 https://www.devze.com 2022-12-25 15:26 出处:网络
Is it possible to store a type name as a C++ variable? For example, like this: type my_type = int; // or string, or Foo, or any other type

Is it possible to store a type name as a C++ variable? For example, like this:

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

I know that 99.9% of the time there's a better way to do what you want without resorting to casting void pointers, but I'm curi开发者_Python百科ous if C++ allows this sort of thing.


No, this is not possible in C++.

The RTTI typeid operator allows you to get some information about types at runtime: you can get the type's name and check whether it is equal to another type, but that's about it.


Not as written, but you could do something similar...

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();
// ...

This kind of thing can be extended depending on what features you need.


You can't do that in C++, but you can use the boost any library then test for the type it holds. Example:

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


No you can't store the type directly as you want, but you can instead store the name of the type.

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

I guess whenever you planned to use that variable for comparison, you could instead at that time compare the str variable against the name() of the types.

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

//....

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

More info available here


Yes, if you code it yourself.

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

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

as commented below, what I left out was that all these "foo" types would have to be related to Foo. Foo would, in essence, be your interface.


Today I had a similar problem while coding:
I had the need to store a polymoriphic data type (here named refobj) over wich call functions of the concrete classes implementing it. I need a solution that doesn't cast the variable explicitly because I need to reduce the amount of code.

My solution (but I haven't tested it yet) looks similar to a previous answer. Actually is quite an experimental solution. It look like this...

// 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!


Types are not objects in C++ (where they are in Ruby, for instance), so you cannot store instances of a type. Actually, types never appear in the executing code (RTTI is just extra storage).

Based on your example, it looks like you're looking for typedefs.

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

Note that a typedef isn't storing the type; it is aliasing the type.


A better process is to have a common base class containing a load method, and an interface for loaders. This would allow other parts of the program to load data generically without knowledge of the descendant class:

struct Load_Interface;

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

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

This design avoids the need to know the types of objects.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号