【问题标题】:Why is this constexpr function giving different results under different circumstances in gcc?为什么这个 constexpr 函数在 gcc 的不同情况下给出不同的结果?
【发布时间】:2015-12-23 08:03:50
【问题描述】:

所以我有以下简单的sn-p:

template <typename T, size_t size>
struct SquareMatrix {
public:
    T data[size * size];
    constexpr T & operator()(const size_t row, const size_t col) noexcept {
        return data[row * size + col];
    }
};

constexpr auto generate() {
    auto result = SquareMatrix<int, 2>{};
    result(0, 0) = 1;
    result(1, 0) = 3;
    result(0, 1) = 2;
    result(1, 1) = 4;
    return result;
}

generate()产生的SquareMatrix&lt;int, 2&gt;中的data数组的预期内容是1, 2, 3, 4。不过……

constexpr auto test = generate();

int main() {
    for (size_t i = 0; i < 4; ++i) {
        std::cout << test.data[i] << std::endl;
    }
    return 0;
}

如果我使用 g++ 5.2 和 -std=c++14 编译并运行此代码,输出到控制台的结果奇怪的是 1032

如果删除 constexpr 限定符以便它在运行时执行,或者如果我改为编写以下任一细微变化:

int main() {
    constexpr auto test = generate();
    for (size_t i = 0; i < 4; ++i) {
        std::cout << test.data[i];
    }
    return 0;
}

...或...

constexpr auto generate() {
    auto result = SquareMatrix<int, 2>{};
    result(0, 0) = 1;
    result(0, 1) = 2; // this line and
    result(1, 0) = 3; // this line have been swapped
    result(1, 1) = 4;
    return result;
}

constexpr auto test = generate();

int main() {
    for (size_t i = 0; i < 4; ++i) {
        std::cout << test.data[i];
    }
    return 0;
}

... 预期的结果1234 被打印出来。此外,clang++ 3.7.0 在所有情况下都会打印预期的1234

我遇到了 g++ 错误还是我在这里遗漏了什么?

【问题讨论】:

    标签: c++ g++ c++14 constexpr


    【解决方案1】:

    这看起来与 gcc 错误 [5 regression] Constant expression factory function initializes std::array with static storage duration strangely 相关,如果我们用 gcc head live example 尝试这个,它工作正常。

    错误报告有以下类似的例子,其中静态变量案例表现出类似的问题,而自动变量案例则没有:

    #include <array>
    #include <cassert>
    
    namespace /* anonymous */
    {
    
      constexpr auto
      make_array(const int val) noexcept
      {
        std::array<int, 2> result = { { val, 0 } };
        return result;
      }
    
      // Replacing `constexpr` by `const` doesn't change anything.
      constexpr auto numbers_static = make_array(42);
    
    }
    
    int main()
    {
      const auto numbers_automatic = make_array(42);
      assert(numbers_automatic[0] == 42);  // okay
      assert(numbers_static[0] == 42);     // fails
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-03
      • 1970-01-01
      • 2017-09-22
      • 1970-01-01
      • 2011-03-27
      • 1970-01-01
      • 2015-11-16
      相关资源
      最近更新 更多