2015-09-25 76 views
9

所以我有以下简单片段:在由generate()产生的SquareMatrix<int, 2>data阵列的为什么这个constexpr函数在gcc的不同情况下会给出不同的结果?

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; 
} 

预期内容是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 ++错误还是我失去了一些东西?

回答

7

这看起来涉及到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 
} 
相关问题