为什么GCC和clang之间编译的c ++ 17 lambdas存在差异?

时间:2017-07-30 09:44:31

标签: c++ gcc lambda clang c++17

在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

标准体是否允许编译器之间发生这种情况?为什么呢?

1 个答案:

答案 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,因此没有区别。