指针类型的C ++模板函数重载

时间:2019-01-14 19:43:21

标签: c++ template-meta-programming

我将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));

奖金说明为什么未选择指针重载。

1 个答案:

答案 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*)应该可以解决此问题。 constU*都比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