我看到了this answer,但我并不满意:它在标准中的哪个类型扣除了' auto'不考虑默认参数?
int main() {
auto lambda = [] (auto subl = [] {}) {};
lambda();
}
答案 0 :(得分:3)
auto
根据模板参数推断使用规则([dcl.spec.auto]
/ P7):
如果占位符是自动 type-specifier ,推导出的类型是使用模板参数推导的规则确定的。
当默认参数的类型是推导出的模板参数([temp.deduct.type] / p5)时,默认参数显式为非推导的上下文:
未推断的上下文是:
- 使用 qualified-id 指定的类型的嵌套名称说明符。
- decltype-specifier 的表达式。
- 非类型模板参数或子表达式引用模板的数组 参数。
- 在具有默认参数的函数参数的参数类型中使用的模板参数 在正在进行参数推断的调用中使用。
答案 1 :(得分:1)
来自 [expr.prim.lambda] :
5 - [...]对于通用lambda,闭包类型有一个公共内联函数调用操作员成员模板(14.5.2),其 template-parameter-list 由一个发明类型组成 template-parameter ,对于lambda的 parameter-declaration-clause 中每次出现的
key
,按出现顺序排列。 [...]
无法从默认参数中推导出模板参数;的 [temp.deduct.call] 强>:
5 - [...] [注意:如果 template-parameter 未在任何一个中使用 函数模板的函数参数,或仅在非推导的上下文中使用,其对应的 template-argument 不能从函数调用中推导出来, template-argument 必须明确地说 指定。 -end note ]
默认参数是非推断的上下文( [temp.deduct.type] / 5)。
答案 2 :(得分:0)
只是添加到上面所说的内容,lamda中的默认参数可以让你在捕获列表时“作弊”。 我们都知道你必须用捕获列表“捕获”外部参数:
int x=7;
auto func = [&x](){ return x+1 ;}
如果您可以使用默认参数,您可以在捕获列表上“作弊”,只需使用默认参数放置引用:
int x=7;
auto func = [](const int& y = x){ return y+1 ;}
阻止默认参数可防止您不捕获外部参数。