我想检查在编译时使用类型名称(即typeid(int),typeid(std :: string)...)评估typeid。
为此,我在一个循环中重复了两个typeid调用的比较,并在启用了优化的情况下对其进行了编译,以便查看编译器是否简化了循环(通过查看执行时间为1us,而不是简化了当它没有时160ms。
我得到了奇怪的结果,因为有时编译器会简化代码,有时则不会。我使用g ++(我试过不同的4.x版本),这是程序:
#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;
}
出现此问题的条件不明确,但是:
- 如果没有涉及继承,没问题(总是编译时间)
- 如果我只进行一次比较,没问题
- 如果所有条款均为假,则问题仅出现在比较分离的情况下
那么有什么东西我没有得到typeid如何工作(它是否总是应该在编译时与类型名称一起使用?)或者这可能是评估或优化中的gcc错误?
关于上下文,我将问题跟踪到这个非常简单的示例,但我的目标是将typeid与模板类型一起使用(因为部分函数模板不可能专门化)。
感谢您的帮助!
答案 0 :(得分:7)
我真的不知道你的问题的答案,但如果你使用is_same&lt;&gt; metafunction而不是typeid你可能会获得更理想的结果。即使您无法访问此元函数,也可以轻松编写一个元函数:
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;
};
答案 1 :(得分:2)
typeid
是运行时类型识别机制的一部分,它表明了它的用处:它的主要用途是在运行时识别指向基类的引用的动态类型。当这些类型在编译时静态知道时,您不需要“识别”它们,因为您已经知道它们是什么。
在这个例子中,没有什么可以在运行时识别,但结果在编译时没有任何用处(typeid
不能出现在const表达式中,这就是模板所需要的元编程)。
因此我也建议is_same
答案 2 :(得分:2)
对于任何类型 T ,如果 T 是多态的,则编译器需要在运行时评估typeid内容。如果T是非多态的,则编译器需要在编译时评估typeid内容。但是,我无法在C ++草案(n3000.pdf)中找到它的相关参考。
事实上,在我参与的一个项目中,这个技巧被用来找到一个类在运行时是否是多态的。
template <class T>
bool isPolymorphic() {
bool answer=false;
T *t = new T();
typeid(answer=true,*t);
delete t;
return answer;
}
几个月前我就提出了一个相关问题here。