Template programming: std::function<> vs lambda not compiling on Clang but GCC.

Dear Clang-Mailinglist,

I found some code which does compile on GCC (7.2) but fails to compile on Clang. Could you enlighten me, whether it should compile or not? It is using if constexpr to type match a template.

  • Clang complains: “function: ‘…’ with deduced return type cannot be used before it is defined.”

  • GCC compiles this fine and main returns “6” as expected.

  • I am using Clang from trunk.

Is Clang right in rejecting this code, or is GCC too permissive in accepting this? Could you let me know, why this is the case?

Here is a really reduced example:

template auto foo() {
if constexpr (I != 0)
return 10;
return foo<1>();
int main() { return foo<0>(); }

gcc seems to apply [dcl.spec.auto]p9 wrongly, I think. It says:

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. Once a non-discarded return statement has been seen in a function, however, the return type deduced from that statement can be used in the rest of the function, including in other return statements.

The key here is “Once a non-discarded return statement […]”. Here, return 10; is a discarded return statement and must be ignored for deduction, and so the first sentence applies to the last return statement. Note that if it weren’t for if constexpr, that function would be well-formed.