C++ 14 lambda的默认参数类型推导取决于前面的参数

nod*_*kai 3 c++ lambda language-lawyer default-parameters c++14

这不是有效的C++ 14吗?

auto f = [](auto x, auto y = std::decay_t<decltype(x)>{}) { };
f(0);
Run Code Online (Sandbox Code Playgroud)

我期待它大致相当于

auto f = [](int x, int y) { };
f(0, int{});
Run Code Online (Sandbox Code Playgroud)

GCC 6.3和Clang 4.0都没有接受我的代码.

是否与我对C++模板演绎阶段缺乏了解有关?1400页长规格实际上对我的问题有明确的答案吗?

更新

总而言之,我的问题实际上可以简化为这段代码(没有lambda,单个参数),并且它在C++ 14下无效(感谢@BaummitAugen和@NirFriedman)

template <typename T>
void f(T x = 0) { }

int main() {
    f();
}
Run Code Online (Sandbox Code Playgroud)

Bau*_*gen 8

编译器拒绝你的代码是正确的,它确实无效C++ 14.

在标准中(在这里使用N4141)我们有

对于泛型lambda,闭包类型有一个公共内联函数调用操作符成员模板(14.5.2),其template-parameter-list由lambda的parameter-declaration-clause中每次出现auto的一个发明类型模板参数组成,按出场顺序.

(5.1.2/4 [expr.prim.lambda]).所以你的电话相当于打电话给某些人

template <class T1, class T2>
auto operator() (T1 x, T2 y = std::decay_t<decltype(x)>{});
Run Code Online (Sandbox Code Playgroud)

现在

如果模板参数仅在非推导的上下文中使用且未明确指定,则模板参数推断将失败.

(14.8.2/4 [temp.deduct.type])和

非推导的上下文是:
[...]
- 在函数参数的参数类型中使用的模板参数,该参数具有在正在进行参数推断的调用中使用的默认参数.

(14.8.2/5 [temp.deduct.type])使你的电话不正常.