`if constexpr`,lambda 内部,包扩展内部——编译器错误?
`if constexpr`, inside lambda, inside pack expansion -- compiler bug?
clang version 5.0.0 (trunk 305664)
Target: x86_64-unknown-linux-gnu
以下代码编译成功:
template <int... A>
void f() {
([](auto) {
if constexpr (A == 0)
return 42;
else
return 3.14;
}(0), ...);
}
int main() {
f<0, 1>();
}
...但是这个没有:
template <int... A>
void f() {
([](auto...) { // Variadic lambda
if constexpr (A == 0)
return 42;
else
return 3.14;
}(), ...); // No argument
}
int main() {
f<0, 1>();
}
...屈服:
<source>:7:13: error: 'auto' in return type deduced as 'double' here but deduced as 'int' in earlier return statement
return 3.14;
^
<source>:3:6: note: in instantiation of function template specialization 'f()::(anonymous class)::operator()<>' requested here
([](auto...) { // Variadic lambda
^
<source>:12:5: note: in instantiation of function template specialization 'f<0, 1>' requested here
f<0, 1>();
^
我不希望空参数包和伪参数之间有不同的行为。
这种差异是有原因的,还是编译器错误?
我认为这是一个 clang 错误。
[dcl.spec.auto] 中的规则是,强调我的:
If the declared return type of the function contains a placeholder type, the return type of the function is deduced from non-discarded return
statements, if any, in the body of the function ([stmt.if]).
[...]
If a function with a declared return type that contains a placeholder type has multiple non-discarded return
statements, the return type is deduced for each such return statement. If the type deduced is not the same in each deduction, the program is ill-formed.
丢弃 lambda 中的一个或另一个 return
语句(if constexpr
中未采用的分支称为 丢弃语句),这只留下一个未丢弃的 return 语句,因此 lambda 的 return 类型应该从剩下的语句中简单地推导出来。
此外,clang 可以这样处理:
template <int A>
void f() {
[](auto...) {
if constexpr (A == 0)
return 42;
else
return 3.14;
}();
}
int main() {
f<0>();
f<1>();
}
所以这可能与 lambda 在包表达式中的工作方式有一些不好的交互。
clang version 5.0.0 (trunk 305664)
Target: x86_64-unknown-linux-gnu
以下代码编译成功:
template <int... A>
void f() {
([](auto) {
if constexpr (A == 0)
return 42;
else
return 3.14;
}(0), ...);
}
int main() {
f<0, 1>();
}
...但是这个没有:
template <int... A>
void f() {
([](auto...) { // Variadic lambda
if constexpr (A == 0)
return 42;
else
return 3.14;
}(), ...); // No argument
}
int main() {
f<0, 1>();
}
...屈服:
<source>:7:13: error: 'auto' in return type deduced as 'double' here but deduced as 'int' in earlier return statement
return 3.14;
^
<source>:3:6: note: in instantiation of function template specialization 'f()::(anonymous class)::operator()<>' requested here
([](auto...) { // Variadic lambda
^
<source>:12:5: note: in instantiation of function template specialization 'f<0, 1>' requested here
f<0, 1>();
^
我不希望空参数包和伪参数之间有不同的行为。
这种差异是有原因的,还是编译器错误?
我认为这是一个 clang 错误。
[dcl.spec.auto] 中的规则是,强调我的:
If the declared return type of the function contains a placeholder type, the return type of the function is deduced from non-discarded
return
statements, if any, in the body of the function ([stmt.if]).[...]
If a function with a declared return type that contains a placeholder type has multiple non-discarded
return
statements, the return type is deduced for each such return statement. If the type deduced is not the same in each deduction, the program is ill-formed.
丢弃 lambda 中的一个或另一个 return
语句(if constexpr
中未采用的分支称为 丢弃语句),这只留下一个未丢弃的 return 语句,因此 lambda 的 return 类型应该从剩下的语句中简单地推导出来。
此外,clang 可以这样处理:
template <int A>
void f() {
[](auto...) {
if constexpr (A == 0)
return 42;
else
return 3.14;
}();
}
int main() {
f<0>();
f<1>();
}
所以这可能与 lambda 在包表达式中的工作方式有一些不好的交互。