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!
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With