2010-05-20 74 views
4

我想檢查typeid是否在編譯時與類型名稱(即typeid(int),typeid(std :: string)...)一起使用時進行評估。類型名稱的typeid總是在編譯時在C++中進行評估?

爲此,我在循環中重複了兩個typeid調用的比較,並在啓用優化的情況下對其進行了編譯,以查看編譯器是否簡化了循環(通過查看簡化爲1us的執行時間而不是160毫秒)。

我得到了奇怪的結果,因爲有時編譯器會簡化代碼,有時它不會。我用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是如何工作的(當它與nam一起使用時,總是應該在編譯時進行評估es?)或者這可能是評估或優化中的gcc錯誤?

關於上下文,我將這個問題追溯到這個非常簡化的例子,但我的目標是使用帶有模板類型的typeid(因爲部分功能模板專業化是不可能的)。

感謝您的幫助!

+0

您是否完全基於您的代碼執行需要多長時間,還是您有更確切的證明編譯器實際輸出的內容? – 2010-05-20 20:38:52

+0

你可以設計你的程序而不需要'typeid'嗎?一個比較對象類型的程序被認爲是一個糟糕的OO程序。 – 2010-05-20 20:49:39

+0

Dennis>是的,但我只是檢查了彙編代碼,我可以確認在一種情況下,在兩個clock_gettime調用之間有6條指令沒有跳轉,另一條指令有2條跳轉指令,包括一個明顯的循環。 – cyril42e 2010-05-20 21:10:28

回答

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

太棒了! 但是我不得不修改一點點的功能才能工作: [模板 結構is_same ] [如果(is_same ::值){}] 並且有boost :: is_same。 非常感謝,我會這樣做的! – cyril42e 2010-05-20 20:47:49

2

typeid是運行時類型識別機制,這表明它是有用的一部分:它的主要用途是在運行時識別指向基類的動態類型。當編譯時靜態地知道類型時,您不需要「識別」它們,因爲您已經知道它們是什麼。

在這個例子中,在運行時沒有任何東西可以識別,但是在編譯時結果沒有任何用處(typeid不能出現在const-expressions中,這是模板元編程所需的)。

所以我也建議is_same

+0

是的,我同意,我不知道is_same,但這確實是我想要的。謝謝! – cyril42e 2010-05-20 21:12:36

2

對於任何類型的牛逼,如果牛逼是多態的,需要編譯器在運行時評估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

+1

好吧,但是你在對象上使用typeid,而不是類型名稱。即使類型是多態的,給定類型名稱在編譯時完全已知,不是嗎? – cyril42e 2010-05-20 21:28:50

+0

做'new' /'delete'而不是隻聲明一個本地對象的意義是什麼? – AnT 2010-05-20 21:31:38

+0

@AndreyT:任何產生'lvalue'的東西都可以用於typeid操作符。我只是爲了完整性而從另一個線索回答。 – Abhay 2010-05-21 01:42:38