我使用 std::type_index 对象作为状态类的唯一标识符(基本上,工厂函数中的键用于生成引用类型的新对象)。类的 ID、该类的对象以及指向该类对象的指针都应该相同。因此,我尝试这样做:
using stateid_t = std::type_index;
template<class T> inline stateid_t GetStateID() { return typeid(T); }
template<class T> inline stateid_t GetStateID(const T&) { return typeid(T); }
template<class T> inline stateid_t GetStateID(const T*) { return typeid(T); }
但是,第三个版本永远不会被像 GetStateID(this);
这样的东西调用,总是第二个版本,T 的类型被推导为“指向 T 的指针”。
我认为我应该能够使用std::enable_if
以某种方式做到这一点,但我似乎想不出任何有效的方法。
编辑
我主要想要的是一组满足的函数
struct A{};
A a;
const A b;
//fixed asserts based on comments
assert(GetStateID<A>() == GetStateID(a));
assert(GetStateID(a) == GetStateID(&a));
assert(GetStateID(a) == GetStateID(b));
//added some new constraints
struct X : public A{};
X x;
assert(GetStateID<A>() != GetStateID<X>());
assert(GetStateID(a) != GetStateID(x));
解释为什么没有选择指针重载的奖励积分。
最佳答案
大概您正在从非 const
调用这些函数成员函数。如果是这样的话 stateid_t GetStateID(const T*)
需要隐式转换(从 U*
到 const U*
,其中 U
是类的类型),而 stateid_t GetStateID(const T&)
不( U
将是 U*
)。在 const
的背景下成员(member)功能您的this
指针已经是 const U *
它不需要隐式转换,应该调用 stateid_t GetStateID(const T*)
.
删除那些 const
应该解决问题。两者U*
和const U*
更喜欢 stateid_t GetStateID(T*)
超过stateid_t GetStateID(T&)
.
但是,您似乎正在尝试实现已解决问题的解决方案。表达式typeid(std::remove_pointer_t<T>);
应该已经生产出你想要的东西了。就您的代码而言,以下内容应该适合您:
using stateid_t = std::type_index;
template<class T> inline stateid_t GetStateID() {
return typeid(std::remove_pointer_t<T>);
}
编辑:为了完成您的界面要求,您可以添加一个函数模板来推导 T
:
template<class T> inline stateid_t GetStateID(T&&) {
return GetStateID<T>();
}
关于C++ 指针类型的模板函数重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54188129/