核心问题: 我希望能够获取一个模板化类的实例,比如说:
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库作为一个例子,但我无法解析他们的缩写,我想我缺少一些正式的技术诀窍。
谢谢!
答案 0 :(得分:4)
如果您想将内容放入地图中,并且需要每个类型的密钥,那么正确的解决方案是使用std::type_info::before()
。导出类可能是值得的,因此您可以提供operator<
,或者将std::type_info::before()
包装在二元谓词中。
答案 1 :(得分:2)
我碰巧在我的libs中有这个hackery(uintxx是我的typedef,有明显的意义) - 没有rtti的工作。 32/64 compat。前几个模板用于定义包含void *
的pointer_uintnamespace 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.
*/
答案 2 :(得分:0)
碰撞的可能性很大,但为了简单起见,你无法击败:
template<class a, class b, class c>
static int getUniqueIdentifier()
{
return sizeof( a ) + sizeof( b ) + sizeof( c );
}
答案 3 :(得分:0)
如果您在一个头文件中执行此操作,则可以使用__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 );
}
答案 4 :(得分:0)
如果启用了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"); }
};
答案 5 :(得分:0)
或者怎么样:
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>{};
答案 6 :(得分:0)
您是希望每个实例还是每个实例?对于后来的
template <...>
class foo
{
public:
static unsigned id;
};
extern unsigned fooCounter;
template <...>
unsigned foo::id = ++fooCounter;
甚至
template <...>
unsigned foo::id = reinterpret_cast<unsigned>(&id);
答案 7 :(得分:0)
重新审视这个问题;在我看来,如果我能保证模板实例化中的某些功能对于该实例化是唯一的,我可以简单地使用该函数的地址作为ID。
当我意识到我不必使用type_id中的实际字符串时,我可以使用字符串的位置。
所以,例如;
template<class a>
foo
{
void id(){}
...
}
将
&foo<int>::id != &foo<float>::id //?
如果这是真的,那么我可以将其用作地图的每个特殊化ID号,而不是依赖于RTTI。