C++14 lambda’s default argument type deduction depending on preceding arguments

 

Questions


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?

Update

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();
}

 

 

————————————————-

Answer

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.

c#,c++14,default-parameters,lambda,language-lawyer

Facebook Comments

Post a comment