首页 > 解决方案 > c++指针类型的模板函数重载

问题描述

我使用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));

解释为什么没有选择指针重载的奖励积分。

标签: c++template-meta-programming

解决方案


大概您是从非const成员函数调用这些函数。如果是这种情况,则stateid_t GetStateID(const T*)需要隐式转换(从类的类型U*const U*where ),而不需要(将是)。在成员函数的上下文中,您的指针已经是不需要隐式转换并且应该调用.Ustateid_t GetStateID(const T&)UU*constthisconst 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>(); 
}

推荐阅读