Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 context, 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!

like image 260
cyril42e Avatar asked Dec 23 '22 02:12

cyril42e


2 Answers

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;
};
like image 166
Edward Strange Avatar answered Dec 26 '22 11:12

Edward Strange


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

like image 35
UncleBens Avatar answered Dec 26 '22 11:12

UncleBens