2010-02-01 51 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