繁体   English   中英

为模板类的实例分配唯一的数字标识符

[英]Assigning Unique Numerical Identifiers to Instances of a Templated Class

核心问题:我希望能够获取模板化类的实例,比如说:

template<class a, class b, class c> class foo;

foo<int, float, double>;

然后做类似的事情:

foo<int, float, double>::value;  //Evaluates to a unique number
foo<long, float, double>::value; //Evaluates to a different unique number
foo<int, float, double>::value;  //Evaulates to the same unique number

除了,真的,它是:

template<class a, class b, class c>
int getUniqueIdentifier()
{
    return foo<a, b, c>::value;
} 

当前解决方案尝试:
我想我想使用Boost :: MPL的“可扩展关联序列”,因为每个元素都有它自己的唯一标识符,但我想我需要能够改变序列,“插入”不做。
我可能正在咆哮错误的树。 (在正面,Dayum,但MPL!)

目的:
重新发明信号和插座系统上的轮子。 组件使用“交换机”创建和注册通道,该交换机将使用唯一标识符将通道放入映射中,从而允许运行时通用性。 我已经尝试查找Qt库作为一个例子,但我不能解析他们的缩写,我想我错过了一些正式的技术诀窍。

谢谢!

如果你想把东西放在一个map中,并且需要一个per-type键,那么正确的解决方案是使用std::type_info::before() 导出类可能是值得的,因此您可以提供operator< ,或者在二进制谓词中将std::type_info::before()包装起来。

我碰巧在我的libs中有这个hackery(uintxx是我的typedef,有明显的含义) - 没有rtti的工作。 32/64 compat。 前几个模板用于定义包含void *的pointer_uint

namespace pgast{

template <size_t size>
struct _pointer_uint{
};

template <>
struct _pointer_uint<2>{
    typedef uint16 intrinsic;
};

template <>
struct _pointer_uint<3>{
    typedef uint32 intrinsic;
};

template <>
struct _pointer_uint<4>{
    typedef uint32 intrinsic;
};

template <>
struct _pointer_uint<5>{
    typedef uint64 intrinsic;
};

template <>
struct _pointer_uint<6>{
    typedef uint64 intrinsic;
};

template <>
struct _pointer_uint<7>{
    typedef uint64 intrinsic;
};

template <>
struct _pointer_uint<8>{
    typedef uint64 intrinsic;
};

typedef _pointer_uint< sizeof(void*) >::intrinsic pointer_uint; 

template <class c>
struct Class_Identifier{
   static pointer_uint id(){
       static char _id;
       return reinterpret_cast<pointer_uint>(&_id);
   }
   template <class c2> 
   bool operator==(const Class_Identifier<c2>& rhs)const{
      return id() == Class_Identifier<c2>::id();
   }
   template <class c2> 
   bool operator<(const Class_Identifier<c2>& rhs)const{
      return id() < Class_Identifier<c2>::id();
   }
};

}//namespace pgast

/*
Copyright (c)1993,2001 J. E. Pendergast Jr. 
*/

碰撞的可能性很大,但为了简单起见,你无法击败:

template<class a, class b, class c>
static int getUniqueIdentifier()
{
    return sizeof( a ) + sizeof( b ) + sizeof( c );
}

如果您在一个头文件中执行此操作,则可以使用__LINE__宏来获取一些唯一编号。 但是,只要它分布在多个文件中,它们就不再是唯一的。

IIRC,VC有一些宏,其值为每次使用宏时递增的数字。 所以,如果你只使用VC,你可以使用它。 但是,这也仅适用于一个翻译单元。

除此之外,我不知道如何从类型中获取唯一数字。

但是,为什么不使用typeid作为地图的密钥类型? 像这样的东西:

typedef std::map< std::type_info, whatever > my_map;

template< typename a, typename b, typename c>
void register_foo(my_map& the_map, const foo<a,b,c>& some_bar, whatever the_whatever) 
{
  the_map.insert( typeid(foo<a,b,c>), the_whatever );
}

如果启用了rtti,则可以连接类的名称,正在实例化模板,然后返回此字符串的哈希值。 通过选择一个好的哈希函数,你可以减少碰撞的几率(也许你也不需要rtti,你可以自己介绍一些rtti):

// basic template for gaining names of the classes:
template<typename T>
class Rtti
{
static std::string GetRTTIName() { return std::string(); }
};

// specialization for the classes, you expect to use:
template<>
class Rtti<float>
{
static std::string GetRTTIName() { return std::string("float"); }
};

或者怎么样:

template<class a, class b, class c, int uniqueId>
class Test
{
public:
    int uid() {
        return uniqueId;
    }
};

int main(int argc, char* argv[])
{
    Test<int, int, int, 5> test1;

    std::cout << test1.uid() << std::endl;

    return 0;
}

如果您希望具有相同模板参数的所有实例具有相同的ID,则可以使用;

template<class a, class b, class c>
class TestId5 : public Test<a, b, c, 5>{};

您是希望每个实例还是每个实例? 对于后来

template <...>
class foo 
{
public:
   static unsigned id;
};

extern unsigned fooCounter;

template <...>
unsigned foo::id = ++fooCounter;

甚至

template <...>
unsigned foo::id = reinterpret_cast<unsigned>(&id);

重温这个问题; 在我看来,如果我能保证模板实例化中的某些功能对于该实例化是唯一的,我可以简单地使用该功能的地址作为ID。

虽然我知道我不必使用type_id中的实际字符串,但我可以使用字符串的位置。

所以,例如;

template<class a>
foo
{
    void id(){}
    ...
}

&foo<int>::id != &foo<float>::id  //?

如果这是真的,那么我可以将其用作地图的每个特殊化ID号,而不是依赖于RTTI。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM