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

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

To do this, I repeated the comparison of two type calls in a loop and compiled it with the optimizations turned on to make sure that the compiler simplified the loop (by looking at the runtime of 1us when it simplifies 160 ms, if it is not).

And I get strange results, because sometimes the compiler simplifies the code, and sometimes not. I am using g ++ (I tried different versions of 4.x) 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 under which this problem appears are unclear, but: - if there is no inheritance, not a problem (always compilation time)
- if I make only one comparison, not a problem - the problem arises only with the disjunction of comparisons, if all members are false

So is there something that I could not handle, how typeid works (should it always be evaluated at compile time when used with type names?), Or could it be a gcc error when evaluating or optimizing?

In the context, I traced the problem to this very simplified example, but my goal is to use typeid with template types (since specialization of partial function templates is not possible).

Thanks for your help!

+4
source share
3 answers

I do not know the answer to your question, but if you use is_same <> metafunction instead of typeid, you can get more desirable results. Even if you do not have access to this metaphor, it is very easy to write it:

 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; }; 
+7
source

typeid is part of the runtime type identification mechanism that offers what is useful to it: the main use is to identify the dynamic type of a pointer / reference to the base class at runtime. When types are statically known at compile time, you do not need to β€œidentify” them, since you already know what they are.

There is nothing in the example that could be identified at run time, but the results cannot be useful at compile time ( typeid cannot appear in const expressions, which is what you need for metaprogramming templates).

Therefore, I also recommend is_same

+2
source

For any type T , if T is polymorphic, the compiler must evaluate the typeid material at runtime. If T is not polymorphic, the compiler should evaluate the typeid material at compile time. However, I cannot find the corresponding link in the C ++ project (n3000.pdf) for it.

Infact, in one of the projects I was working on, this trick was used to determine if 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 asked a related question here a few months ago.

+2
source

Source: https://habr.com/ru/post/1310420/


All Articles