简单的模板推导错误

时间:2015-09-06 17:14:11

标签: c++ templates

我正在尝试使用一些模板自动生成const成员函数对。请帮我编译这段代码。

template<typename T>
struct Constifier
{
  typedef T Type;
};

template<typename T>
struct Constifier<T &>
{
  typedef const T &Type;
};

template<typename T>
struct Constifier<T &&>
{
  typedef const T &&Type;
};

template<typename T>
struct Constifier<T *>
{
  typedef const T *Type;
};

template<typename F>
struct ReturnType;

template<typename R, typename ...Ts>
struct ReturnType<R (*)(Ts ...ts)>
{
  typedef R Type;
};

template<typename R, typename T, typename ...Ts>
struct ReturnType<R (T::*)(Ts ...ts)>
{
  typedef R Type;
};

template<typename T, typename F, typename ...Ts>
auto callConstVersion(const T *t, F f, Ts ...ts)
{
  return const_cast<typename Constifier<typename ReturnType<F>::Type>::Type>((const_cast<T *>(t)->*f)(ts...));
}

struct A
{
  A *p;
  A *get() {return p;}
  const A *get() const {return callConstVersion(this, &A::get);}
};

1 个答案:

答案 0 :(得分:1)

get成员函数被重载,因此,&A::get作为参数,F变为不可推导。要消除两者之间的歧义,请使用static_cast

static_cast<const A*(A::*)() const>(&A::get) // for the const overload

static_cast<A*(A::*)()>(&A::get) // for the non-const overload

或在模板参数列表中明确指定F

callConstVersion<A,A*(A::*)()>(this, &A::get);

或者如果您知道callConstVersion应始终采用非const非易失性非重新限定成员函数,则可以按如下方式重新定义:

template<typename T, typename R, typename... Args, typename ...Ts>
auto callConstVersion(const T *t, R(T::*f)(Args...), Ts ...ts)

(然后普通callConstVersion(this, &A::get)应该有用)。