递归泛型 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 可能会证明绕过它并非总是不可能,但通常标准禁止它。
下面的代码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 可能会证明绕过它并非总是不可能,但通常标准禁止它。