tags:

views:

220

answers:

5

Why is typeid(someType) not constant like sizeof(someType) ?

This question came up because recently i tried something like:

template <class T>
class Foo
{
    BOOST_STATIC_ASSERT(typeid(T)==typeid(Bar) || typeid(T)==typeid(FooBar));
};

And i am curious why the compiler knows the size of types (sizeof) at compile time, but not the type itself (typeid)

+2  A: 

Because typeid requires RTTI, i.e, typeid is performed at runtime and BOOST_STATIC_ASSERT is performed at compile time.

More information here.

coelhudo
except smerlin was asking about a particular use of typeid, and this particular use of typeid does not do runtime lookup
Aaron
I disagree, his question: "Why is typeid(someType) not constant like sizeof(someType) ?", and not about a particular use of typeid
coelhudo
Coelhudo, the "particular use" is the one in which the argument is a *type*. RTTI is only used when the argument is an object expression.
Rob Kennedy
I see, thanks for explanation :)
coelhudo
And then RTTI is also only used if the object expression is of polymorphic type. In other words, `pair<int, int> p; typeid(p);` does not need RTTI.
Johannes Schaub - litb
A: 

It knows the type itself (in its own internal language) at compile time, but not its type id (which has clearly been created for runtime).

Benoît
+1  A: 

Because typeid has the flexibility to do lookups at runtime based on a pointer or reference to an object, it can't return a compile-time constant. Even when it looks like it could. sizeof has no such restrictions, as it always does its calculation at compile time.

Mark Ransom
except smerlin was asking about a particular use of typeid, and this particular use of type id does _not_ do runtime lookup.
Aaron
Runtime constants are generally limited to integer values. `typeid` returns a reference to a `type_info` class, which is much more than that.
Mark Ransom
Ah i forgot that typeid works for objects aswell ... still i think it would be very useful if something like the example above could be done with it.Hopefully C++0x supports something like that.Well at least it will support static asserts...
smerlin
+4  A: 

C++ can handle constant (compile-time) expressions of some types, but reference types are not among those types. The result of a typeid expression is a reference to a std::type_info object.

Apparently for a while in 2008, the C++ standard committee had typeid expressions such as the ones in your example behaving as constant expressions, just like sizeof. However, according to this comment, that change was ultimately reverted.

Jason Orendorff
+4  A: 

When you are dealing with types, you'd rather use simple metaprogramming techniques:

#include <boost/static_assert.hpp>
#include <boost/type_traits.hpp>

template <class T>
void Foo()
{
    BOOST_STATIC_ASSERT((boost::is_same<T, int>::value || boost::is_same<T, double>::value));
}

int main()
{
    Foo<int>();
    Foo<float>();
}

where is_same could be implemented like this:

template <class A, class B>
struct is_same
{
    static const bool value = false;
};

template <class A>
struct is_same<A, A>
{
    static const bool value = true;
};

typeid probably isn't compile-time because it has to deal with runtime polymorphic objects, and that is where you'd rather use it (if at all).

UncleBens