我需要一种方法来为任何类型生成唯一标识符(字符串或整数),以便在一组模板函数中使用。 type_info::name()
的文档说对于不同类型可能会有所不同,也可能没有什么不同,这让我很担心,因为我需要依赖它们是唯一的。 hash_code
可能也不是唯一的(从名称来看,我没有看过标准对此有何看法)。
我的问题主要是,在typeid(T).name()
的情况下,
由于类型可以来自不同的(DLL)模块,因此我不能简单地使用全局计数器和模板静态函数。但是线程安全不是问题,因为可能需要类型ID的函数一次只能被一个线程调用。
答案 0 :(得分:3)
我需要一种方法来生成唯一标识符(字符串或 对于在一组模板函数中使用的任何类型的整数)。
这些内容会有所帮助吗?
#include <cstdint>
#include <iostream>
using namespace std;
template <typename T>
class unique_id {
static char type_id;
public:
static uintptr_t get_ID() { return reinterpret_cast<uintptr_t>(&type_id); }
};
template <typename T>
char unique_id<T>::type_id;
struct { } s;
int main() {
cout << unique_id<int >::get_ID() << endl;
cout << unique_id<double >::get_ID() << endl;
cout << unique_id<decltype(s) >::get_ID() << endl;
cout << unique_id<size_t >::get_ID() << endl;
cout << unique_id<unsigned long>::get_ID() << endl;
}
LLVM代码库中有类似的,因为它不使用RTTI。但是,我没有找到该技巧的描述。即使是30分钟的谷歌搜索也无济于事;我放弃了。
我的问题主要是,在什么情况下,typeid(T).name()不是唯一的?
我不知道答案。我的猜测是标准并没有强制要求;当然,它没有回答问题的原因。
好的,请参阅Michael J's answer。
更新:至于std::type_info::name()
,标准似乎没有保证;返回的字符串对于多种类型可以是相同的,并且在同一程序的调用之间进行更改。
一个选择是深入实现定义的土地:我只是在我关心的类型以及我关心的所有平台和编译器上测试它。如果它工作正常,那么我可能会冒险。
但是,std::type_info::operator==
和std::type_info::operator!=
可以解决您的问题:您可以区分彼此的类型,甚至可以保证它们。在您的应用程序中是否比较字符串或type_info对象是否重要?
答案 1 :(得分:0)
有时,多个名称可以引用相同的类型。希望下面的例子能给你一个想法
#include <typeinfo>
#include <iostream>
int main()
{
class Foo
{
};
class Bar : public Foo
{
};
typedef int my_int;
std::cout << "int8_t = " << typeid(int8_t).name() << std::endl;
std::cout << "int16_t = " << typeid(int16_t).name() << std::endl;
std::cout << "int32_t = " << typeid(int32_t).name() << std::endl;
std::cout << "int64_t = " << typeid(int64_t).name() << std::endl;
std::cout << "short = " << typeid(short).name() << std::endl;
std::cout << "short int = " << typeid(short int).name() << std::endl;
std::cout << "int = " << typeid(int).name() << std::endl;
std::cout << "long = " << typeid(long).name() << std::endl;
std::cout << "long int = " << typeid(long int).name() << std::endl;
std::cout << "long long = " << typeid(long long).name() << std::endl;
std::cout << "long long int = " << typeid(long long int).name() << std::endl;
std::cout << "my_int = " << typeid(my_int).name() << std::endl;
std::cout << "Foo = " << typeid(Foo).name() << std::endl;
std::cout << "Bar = " << typeid(Bar).name() << std::endl;
return 0;
}
int8_t = signed char
int16_t = short
int32_t = int
int64_t = __int64
short = short
short int = short
int = int
long = long
long int = long
long long = __int64
long long int = __int64
my_int = int
Foo = ?AVFoo@?1?main@
Bar = ?AVBar@?1?main@