开发者

Is typeid of type name always evaluated at compile time in c++?

I wanted to check that typeid is evaluated at compile time when used with a type name (ie typeid(int), typeid(std::string)...).

To do so, I repeated in a loop the comparison of two typeid calls, and compiled it with optimizations enabled, in order to see if the compiler simplified the loop (by looking at the execution time which is 1us when it simplifies instead of 160ms when it does not).

And I get strange results, because sometimes the compiler simplifies the code, and sometimes it does not. I use g++ (I tried different 4.x versions), and here is the program:

#include <iostream>
#include <typeinfo>
#include <time.h>

class DisplayData {};

class RobotDisplay: public DisplayData {};
class SensorDisplay: public DisplayData {};

class RobotQt {};
class SensorQt {};

timespec tp1, tp2;
const int n = 1000000000;

int main()
{
    int avg = 0;
    clock_gettime(CLOCK_REALTIME, &tp1);
    for(int i = 0; i < n; ++i)
    {
//      if (typeid(RobotQt) == typeid(RobotDisplay))    // (1) compile time
//      if (typeid(SensorQt) == typeid(SensorDisplay))  // (2) compile time
        if (typeid(RobotQt) == typeid(RobotDisplay) || 
            typeid(SensorQt) == typeid(SensorDisplay))    // (3) not compile time ???!!!
            avg++;
        else
            avg--;
    }
    clock_gettime(CLOCK_REALTIME, &tp2);
    std::cout << "time (" << avg << "): " << 
        (tp2.tv_sec-tp1.tv_sec)*1000000000+(tp2.tv_nsec-tp1.tv_nsec) << 
        " ns" << std::endl;
}

The conditions in which this problem appear are not clear, but:

- if there is no inheritance involved, no problem (always compile time)

- if I do only one comparison, no problem

- the problem only appears only with a disjunction of comparisons if all the terms are false

So is there something I didn't get with how typeid works (is it always supposed to be evaluated at compilation time when used with type names?) or may this be a gcc bug in evaluation or optimization?

About the contex开发者_JS百科t, I tracked down the problem to this very simplified example, but my goal is to use typeid with template types (as partial function template specialization is not possible).

Thanks for your help!


I don't really know the answer to your question but if you use is_same<> metafunction instead of typeid you might get more desirable results. Even if you don't have access to this metafunction, it is very easy to write one:


template < typename T1, typename T2 >
struct is_same
{
  enum { value = false }; // is_same represents a bool.
  typedef is_same<T1,T2> type; // to qualify as a metafunction.
};

template < typename T >
struct is_same
{
  enum { value = true };
  typedef is_same<T,T> type;
};


typeid is part of the Run-Time Type Identification mechanism, which suggests what it's useful for: it's main usage is identifying the dynamic type of a pointer/reference to a base class at runtime. When the types are statically known at compile-time, you don't need to "identify" them as you already know what they are.

In the example, there is nothing to identify at runtime, though, yet the results are not in any way useful at compile-time (typeid cannot appear in const-expressions, which is what you need for template metaprogramming).

Therefore I also recommend is_same


For any type T, if T is polymorphic, the compiler is required to evaluate the typeid stuff at runtime. If T is non-polymorphic, the compiler is required to evaluate the typeid stuff at compile time. However, i cannot find the relevant reference in the C++ draft (n3000.pdf) for it.

Infact, in one of the projects that i worked on, this trick was used to find whether a class was polymorphic at runtime.

template <class T>  
bool isPolymorphic() {  
    bool answer=false; 
    T *t = new T(); 
    typeid(answer=true,*t);  
    delete t; 
    return answer;  
} 

I had asked a related question here on SO a few months back.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜