【问题标题】:Unique Numerical ID for a Templated Class using Function Address使用函数地址的模板类的唯一数字 ID
【发布时间】:2010-02-01 07:43:20
【问题描述】:

所以,这个问题之前有人问过,但我想要一个标题中包含一些关键词的问题。

问题很简单:我怎样才能有一个模板类,这样对于模板的每个实例——但不是类的每个实例——都有一个唯一的数字标识符?

也就是一种区分方式:

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

【问题讨论】:

    标签: c++ class templates metaprogramming unique-id


    【解决方案1】:
    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。

    虽然,也许我错过了什么?

    【讨论】:

    • 我选择了自己的答案,因为它 a) 更简单 b) 静态编译时间常数,afaik。
    • 我用 VS 2015 对此进行了测试,它在为 Debug 编译时有效,但在为 Release 编译时无效。在为 Release 编译时,优化器将所有 classID() 函数组合成一个函数。所以 foo.classID == foo2.classID == foo3.classID。
    【解决方案2】:

    我认为您可以为此使用静态函数,并继承其类:

    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(在 boost 和其他库中找到,编写起来很简单),它会产生一个编译时间常数

    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]; }
    

    【讨论】:

    • is_same,AFAIK 的问题在于它不支持 > 或
    • 这满足所有要求,但是,您指出它不是静态编译时间常数?你知道我自己的答案是不是? (我想会,但我不确定如何测试。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-03
    • 1970-01-01
    • 2010-12-13
    • 2021-12-15
    • 2011-11-26
    相关资源
    最近更新 更多