if constexpr in a recursive generic lambda: different compiler behavior

  • A+
Category:Languages

The following code compiles successfully with g++ 7.3.0 and fails to compile with clang++ 6.0.0 (compilation flags are -std=c++17 -Wall -Wextra -Werror -pedantic-errors):

auto foo = [](auto, auto... tail) {     if constexpr (sizeof...(tail) > 0)     {         return foo(tail...);     }     else     {         return 42;     } };  int main() { } 

clang++ compilation error message:

error: variable 'foo' declared with deduced type 'auto' cannot appear in its own initializer

return foo(tail...); 

What behavior is standard compliant in this case?


Clang is right to reject this according to [dcl.spec.auto]/10, as of C++17.

If the type of an entity with an undeduced placeholder type is needed to determine the type of an expression, the program is ill-formed.

The type of foo is needed to resolve the recursive call (find operator(), etc). It's needed to determine the closure type. Since the closure type is being deduced here... you see where it goes.

GCC may prove it's not always impossible to get around it, but in general the standard prohibits it.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: