问题 指定模板函数参数的默认值


你能解释为什么下面的代码不能编译吗?一个明显的解决方法是添加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;
}

9693
2017-08-20 12:30


起源

你没有模板的默认值。 - CyberGuy
请注意你的 Identity 功能总是一个 复制  - 那是故意的吗? - Kerrek SB
@KerrekSB:这不是故意的。它与问题有关吗? - Andrey
@Andrey:不,这只是一个评论。 - Kerrek SB
@KerrekSB:如果要制作副本有什么危险? (可能,这将是一个单独的问题:)) - Andrey


答案:


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

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


5
2017-08-20 12:40





模板参数推导不起作用 - 您无法从默认值推导出参数的类型。但是,在C ++ 11中,您可以指定默认模板参数:

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

9
2017-08-20 12:37



你能解释一下你的判决吗? you can't deduce the type of an argument from a defaulted value 在你的答案中有例子吗?谢谢 - Mr.Anubis
@Anubis先生:我的意思是你不能推断出类型 fn 来自作为默认函数参数给出的值。参数推断只能在调用站点指定的函数参数上执行。 - Kerrek SB
啊,明白了,谢谢+1 :) - Mr.Anubis


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

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


0
2017-08-20 12:32