12

你能解释一下为什么下面的代码不能编译吗?一个明显的解决方法是添加 1 参数重载Apply,有更简单的吗?

template <typename T>
T Identity(const T& i_val)
  {
  return i_val;
  }

template <typename Val, typename Fn>
Val Apply(const Val& v, Fn fn = Identity<Val>)
  {
  return fn(v);
  }

int main() {
  Apply(42);              // error: no matching function for call to 'Apply(int)'
  Apply(42, Identity<int>); // OK
  return 0;
}
4

3 回答 3

10

模板参数推导不是这样工作的——你不能从默认值中推导出参数的类型。但是,在 C++11 中,您可以指定默认模板参数:

template <typename Val, typename Fn = Val(&)(Val const &)>
Val Apply(const Val& v, Fn fn = Identity<Val>)
{
   return fn(v);
}
于 2012-08-20T12:37:27.333 回答
6

查找要调用的函数包括: 1. 创建候选集,其中包括模板参数推导 2. 确定最佳重载

如果我正确理解标准,只有实际的函数参数(即,不是默认的)参与推导模板参数。因此,从参数42中,编译器只能推断出Val= int。重载不会进入候选集,并且从不查看默认参数。

于 2012-08-20T12:40:33.877 回答
0

Apply 是一个模板化的函数。你需要做Apply<MyValueType,MyFuncType>(42);

您可以合理地期望编译器推断Valint,但您不能期望它推断函数的类型,即使您已经给出了默认参数。因此,它不会推断您正在尝试调用该Apply函数的声明。

于 2012-08-20T12:32:53.417 回答