例如,我编写了以下代码:
struct default_type {};
template <typename U = default_type> auto func(int x, U u) {
if constexpr(is_same<U, default_type>::value) {
return x * 2;
}
else {
return u(x);
}
}
int main() {
cout << "5 + 3 = " << func(5, [](int x){ return x + 3; }) << endl;
cout << "5 * 2 = " << func(5) << endl;
}
但是,这将导致编译器错误为“没有匹配函数可调用'func(int)'”。正确的方法是什么?
答案 0 :(得分:3)
您提供了默认类型,但没有提供默认值。该函数仍然需要两个参数,default_type
将被推导的参数覆盖,从而使其无效。
执行以下操作:
template <typename U = default_type>
auto func(int x, U u = {}) { ... } // (1)
我不能完全按照标准的标准来支持这一点,但是简而言之:U
是在模板参数推导阶段获得的(没有推导规则-不考虑默认函数参数, (因此为默认值),该值位于重载解析阶段之前,此时,已经知道U
的类型,从而解释了默认函数参数,从而使列表初始化有效。
是的,您也可以写:
template <typename U = default_type>
auto func(int x, U u = U()) { ... } // (2)
或
template <typename U = default_type>
auto func(int x, U u = default_type()) { ... } // (3)
在显式提供U
类型(我不认为会提供)时,语义略有不同:
func<not_the_default_type>(5);
这里,(1)和(2)是等效的,但是在(3)中,U
的构建是通过构造一个default_type
临时变量来完成的,然后将该临时变量转换为not_the_default_type
最后,完全相反的错误是期望在这里推论U
:
template <typename U>
auto func(int x, U u = default_type()) { ... }
情况并非如此。参见this Q&A。