在GCC 7.1和clang 4.0上再现,也在2017年7月30日的两个快照上再现。
示例1:调用除return语句之外的lambdas,两个编译器的行为都不同。
int main()
{
auto sum = [](auto ... a) { return (... + a); };
auto value1{sum(5,5)}; // Having optimization disabled -O0,
// GCC treats this line as if constexpr is there,
// clang doesn't.
constexpr auto value2{sum(1,2,3,4)}; // Both treat this line as constexpr like expected.
// As a result, in GCC, no trace of lambdas in the executable,
// and only one lambda in clang.
return value1 + value2;
}
Live @godbolt
示例2和3:在return语句中调用lambdas,两个编译器的行为方式相同:运行时评估/没有constexpr。
int main()
{
auto sum = [](auto ... a) { return (... + a); };
return sum(5,5) + sum(1,2,3,4); // Both compilers generate 2 lambdas like expected.
}
Live @godbolt
int main()
{
constexpr auto sum = [](auto ... a) { return (... + a); };
return sum(5,5) + sum(1,2,3,4); // Both compilers generate 2 lambdas like expected.
}
Live @godbolt
标准体是否允许编译器之间发生这种情况?为什么呢?
答案 0 :(得分:4)
调用lambdas而不是return语句,两个编译器的行为都不同。
它们可能会输出不同的程序集,但它们具有完全相同的行为。这是标准保证的,没有别的。所以在这方面,两者都是正确的,因为它们都返回20
。
constexpr
个表达式。没有什么禁止实现调用add
而不是在以下示例中优化它:
constexpr int add(int lhs, int rhs) {
return lhs + rhs;
}
int main() {
return add(4, 5);
}
他们可以,但这并不意味着他们必须。标准尝试在编译时尽可能多地给予实现自由,例如允许大量优化,这部分是未定义行为和形成错误的原因;不需要诊断存在(如果我错了,请纠正我)。
请注意,使用-O3
进行编译会导致两个编译器在您的三个示例中返回20
,因此没有区别。