2015-09-25 24 views
9

Vì vậy, tôi có đoạn mã đơn giản sau đây:Tại sao hàm constexpr này cho kết quả khác nhau trong các trường hợp khác nhau trong 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; 
} 

Nội dung dự kiến ​​của mảng data trong SquareMatrix<int, 2> sản xuất bởi generate()1, 2, 3, 4. Tuy nhiên ...

constexpr auto test = generate(); 

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

Nếu tôi biên dịch và chạy mã này sử dụng g ++ 5.2 và -std=c++14, kết quả được in ra cửa sổ Console là, kỳ lạ, 1032.

Nếu loại bỏ các vòng loại constexpr để nó thực hiện trong thời gian chạy, hoặc nếu tôi thay vì viết một trong hai thay đổi nhỏ sau:

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

... hoặc ...

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

.. Kết quả mong đợi, 1234, được in. Ngoài ra, clang ++ 3.7.0 in các mong đợi 1234 trong mọi trường hợp.

Tôi đã gặp lỗi g ++ hay tôi thiếu gì đó ở đây?

Trả lời

7

Điều này có vẻ liên quan đến lỗi gcc [5 regression] Constant expression factory function initializes std::array with static storage duration strangely và nếu chúng tôi thử điều này với gcc head live example hoạt động tốt.

Các báo cáo lỗi có ví dụ tương tự sau, nơi mà các trường hợp biến tĩnh trưng bày một vấn đề tương tự khi các trường hợp biến tự động không:

#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 
} 
Các vấn đề liên quan