递归泛型 lambda 中的 if constexpr:不同的编译器行为

if constexpr in a recursive generic lambda: different compiler behavior

下面的代码compiles successfully with g++ 7.3.0 and fails to compile with clang++ 6.0.0(编译标志是-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++编译报错信息:

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

return foo(tail...);

在这种情况下,什么行为符合标准?

根据 [dcl.spec.auto]/10,从 C++17 开始,Clang 是正确的。

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.

需要 foo 的类型来解析递归调用(查找 operator() 等)。需要确定闭包类型。由于闭包类型是在这里推导出来的……你看它的去向。

GCC 可能会证明绕过它并非总是不可能,但通常标准禁止它。