Is this not valid as C++14?
auto f = [](auto x, auto y = std::decay_t<decltype(x)>{}) { };
f(0);
I was expecting it to be roughly equivalent to
auto f = [](int x, int y) { };
f(0, int{});
Neither GCC 6.3 nor Clang 4.0 accepted my code.
Is it related to my lack of understanding of C++ template deduction phases? Does the 1400 pages long spec actually has an explicit answer to my question?
To summarize, my problem can in fact be reduced to this piece of code (free of lambda, single parameter) and it is invalid under C++14 (thanks @BaummitAugen and @NirFriedman)
template <typename T>
void f(T x = 0) { }
int main() {
f();
}
The compilers are correct to reject your code, it is indeed not valid C++14.
In the standard (using N4141 here) we have
For a generic lambda, the closure type has a public inline function call operator member template (14.5.2) whose template-parameter-list consists of one invented type template- parameter for each occurrence of auto in the lambda’s parameter-declaration-clause, in order of appearance.
(5.1.2/4 [expr.prim.lambda]). So your call is equivalent to a call to some
template <class T1, class T2>
auto operator() (T1 x, T2 y = std::decay_t<decltype(x)>{});
Now
If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails.
(14.8.2/4 [temp.deduct.type]) and
The non-deduced contexts are:
[...]
- A template parameter used in the parameter type of a function parameter that has a default argument that is being used in the call for which argument deduction is being done.
(14.8.2/5 [temp.deduct.type]) makes your call ill-formed.