2010-02-01 50 views
0

所以,這個問題之前已經被問過了,但我想要一個關於標題中的一些關鍵詞的問題。使用函數地址的模板類的唯一數字ID

問題很簡單:我如何擁有一個模板化類,以便模板的每個實例(而不是每個類的實例)都有一個唯一的數字標識符?

也就是說,一個方法來區分:

foo<int> f1; 
foo<char> f2; 
classID(f1) != classID(f2); 

但是,

foo<int> f3; 
foo<int> f4; 
classID(f3) == classID(f4); 

相關的:

in C++, how to use a singleton to ensure that each class has a unique integral ID?

Assigning Unique Numerical Identifiers to Instances of a Templated Class

回答

3
template<class T> 
class Base 
{ 
public: 
    static void classID(){} 
private: 
    T* t; 
}; 

int main() 
{ 
    Base<int> foo; 
    Base<int> foo2; 
    Base<char> foo3; 

    /* 
    unsigned int i = reinterpret_cast<unsigned int>(Base<int>::classID); 
    unsigned int ii = reinterpret_cast<unsigned int>(Base<char>::classID); 
    unsigned int iii = reinterpret_cast<unsigned int>(Base<int>::classID); 
    /*/ 
    unsigned int i = reinterpret_cast<unsigned int>(foo.classID); 
    unsigned int ii = reinterpret_cast<unsigned int>(foo2.classID); 
    unsigned int iii = reinterpret_cast<unsigned int>(foo3.classID); 
    //*/ 

    return ((i != ii) + (i <= ii) + (i >= ii)) == 2; 
} 

就是這樣!這是輕量級的,超級簡單,並且不使用RTTI,儘管它使用了可笑的不安全的reinterpret_cast。

雖然,也許我錯過了什麼?

+0

我選擇我自己的答案,因爲它是)比較簡單和b)靜態編譯時間常數, 據我所知。 – Narfanator 2010-02-11 05:29:43

+0

我使用VS 2015測試了它,它在編譯調試時工作,但在編譯Release時不起作用。編譯Release時,優化器將所有classID()函數合併爲一個。所以foo.classID == foo2.classID == foo3.classID。 – adigostin 2016-03-17 08:43:55

+0

該死的。必須找到一個新的技巧,現在... – Narfanator 2016-03-19 18:23:22

1

我想你可以使用這個靜態函數,並繼承其類:

struct IdCounter { static int counter; }; 
int IdCounter::counter; 

template<typename Derived> 
struct Id : IdCounter { 
    static int classId() { 
    static int id = counter++; 
    return id; 
    } 
}; 

struct One : Id<One> { }; 
struct Two : Id<Two> { }; 

int main() { assert(One::classId() != Two::classId()); } 

當然,這不會是一個靜態編譯時間常數 - 我不認爲這是可能的自動(你必須手動添加這些類型到一些類型列表,如mpl::vector)。請注意,爲了比較類型的平等性,你不需要所有這些。你只需要使用is_same(升壓和其他圖書館和瑣碎寫找到),它產生一個編譯時間常數

template<typename A, typename B> 
struct is_same { static bool const value = false; }; 
template<typename A> 
struct is_same<A, A> { static bool const value = true; }; 

int main() { char not_true[!is_same<One, Two>::value ? 1 : -1]; } 
+0

「'is_same'',AFAIK的問題是它不支持>或<,這意味着它不可排序,因此不能使用任何有效的存儲對象樹或地圖。 – Narfanator 2010-02-01 22:33:55

+0

這符合所有要求,但是,您指出它不是一個靜態編譯時間常量?你知道我自己的答案是嗎? (我認爲會,但我不知道如何測試。) – Narfanator 2010-02-01 22:35:28