我将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));
奖金说明为什么未选择指针重载。
答案 0 :(得分:3)
大概是从非const
成员函数中调用这些函数。如果是这种情况,则stateid_t GetStateID(const T*)
需要隐式转换(从U*
到const U*
,其中U
是类的类型),而stateid_t GetStateID(const T&)
不需要({{ 1}}将是U
)。在U*
成员函数的上下文中,您的const
指针已经是一个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