4

我想检查 typeid 在与类型名称(即 typeid(int)、typeid(std::string)...)一起使用时在编译时进行评估。

为此,我在一个循环中重复了两个 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 与模板类型一起使用(因为无法实现部分函数模板特化)。

谢谢你的帮助!

4

3 回答 3

7

我真的不知道你的问题的答案,但如果你使用 is_same<> 元函数而不是 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;
};
于 2010-05-20T20:19:56.493 回答
2

typeid是运行时类型识别机制的一部分,这表明它的用途:它的主要用途是在运行时识别对基类的指针/引用的动态类型。当类型在编译时静态已知时,您不需要“识别”它们,因为您已经知道它们是什么。

在这个例子中,虽然在运行时没有什么可识别的,但是结果在编译时没有任何用处(typeid不能出现在 const 表达式中,这是模板元编程所需要的)。

所以我也推荐is_same

于 2010-05-20T21:04:58.930 回答
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;  
} 

几个月前我在这里问过一个相关的问题。

于 2010-05-20T21:23:37.910 回答