[英]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.