Storing a type in C++

54,414

Solution 1

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.

Solution 2

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.

Solution 3

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

Solution 4

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

Solution 5

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.

Share:
54,414
perimosocordiae
Author by

perimosocordiae

I enjoy a good crepe.

Updated on April 25, 2021

Comments

  • perimosocordiae
    perimosocordiae about 3 years

    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 curious if C++ allows this sort of thing.

  • sbi
    sbi about 14 years
    Number isn't a variable, i.e., it's meaning can't be changed at run-time.
  • perimosocordiae
    perimosocordiae about 14 years
    Cool, I hadn't seen that before.
  • Andres Jaan Tack
    Andres Jaan Tack about 14 years
    Noted. Based on his example, though, I don't think he's actually looking for storage.
  • perimosocordiae
    perimosocordiae about 14 years
    You're right that my example isn't doing anything a typedef can't do, but I would have ultimately liked to store the type (as a member of a class, say). Sorry for the confusion.
  • Michael Aaron Safyan
    Michael Aaron Safyan about 14 years
    Except that name() isn't guaranteed to be the same across platforms!
  • Brian R. Bondy
    Brian R. Bondy about 14 years
    @Michael: I did not suggest saving it to a file
  • Dennis Zickefoose
    Dennis Zickefoose about 14 years
    Strictly speaking, there is no guarentee that ’shared_pointer<Foo>’ is large enough to store all those different types unless ’Foo’ is related to them in some way. Also, ’_AFOO’ is an illegal identifier.
  • wheaties
    wheaties about 14 years
    duly noted and fixed. I'll add comments about "Foo"
  • Michael Aaron Safyan
    Michael Aaron Safyan about 14 years
    The name isn't portable, though.
  • user1095108
    user1095108 about 11 years
    You don't need Foo at all, you can just do boost::shared_ptr<void>, with appropriate deleters.
  • RamblingMad
    RamblingMad about 10 years
    It is portable, just not between compilers. An application compiled with GCC on linux will have the same type names as GCC on windows, but not the same as the VS compiler.
  • David Doria
    David Doria over 8 years
    @Thomas Is this en.cppreference.com/w/cpp/types/type_info the operator you're talking about? This isn't an operator, right? But rather a class that stores the result of typeid()?
  • Keyur Padalia
    Keyur Padalia over 8 years
    Fail on my part. It's typeid. Editing... (11 upvotes without anyone mentioning this glaring mistake), thanks for spotting!
  • degski
    degski over 8 years
    Hi Micheal. I'm almost there with your snippet. The cast function in the derived class returns a void pointer in your code. How do I get the T* as desired?
  • Michael Aaron Safyan
    Michael Aaron Safyan over 8 years
    You can explicitly in the caller if you know that the object is of the correct type. However, the reflective API that operates on any type can't reasonably have strongly-typed methods; the methods for the general type representation would need to operate on weakly-typed objects (void* in conjunction with some record of the type).
  • Chad Mourning
    Chad Mourning about 4 years
    Boost isn't magic, if they can do it in C++, you can do it in C++, it just probably isn't easy.
  • Joan Marcè i Igual
    Joan Marcè i Igual over 2 years
    A better way could be to do using Number = int;
  • X...
    X... over 2 years
    What does method cast achieve here? It only returns a void* pointer which has to be explicitly static_cast<T*> to a specific class before it can be used.