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>();
^
我不希望在空参数包和伪参数之间有不同的行为。
是否存在这种差异的原因,或者这是编译器错误?
答案 0 :(得分:3)
我相信这是一个铿锵的错误。
[dcl.spec.auto]中的规则强调我的:
如果函数的声明返回类型包含占位符类型,则函数的返回类型是从非丢弃
return
语句(如果有)中推导出来的。 function([stmt.if])。[...]
如果具有包含占位符类型的声明返回类型的函数具有多个非丢弃
return
语句,则会为每个此类返回语句推断返回类型。如果推断的类型在每次扣除中不相同,则该程序格式不正确。
lambda中的一个或另一个return
语句被丢弃(if constexpr
中的非采用分支称为废弃语句),只留下一个非语句丢弃的return语句,所以lambda的返回类型应该简单地从剩下的那个中推导出来。
此外,铿锵就是这样:
template <int A>
void f() {
[](auto...) {
if constexpr (A == 0)
return 42;
else
return 3.14;
}();
}
int main() {
f<0>();
f<1>();
}
因此,可能与lambdas在包表达式中的工作方式有一些不良的交互。