2015-09-25 10 views
9

Więc mam następujący prosty fragment:Dlaczego ta funkcja constexpr daje różne wyniki w różnych okolicznościach w 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; 
} 

Oczekiwane Zawartość tablicy data w SquareMatrix<int, 2> produkowanego przez generate() jest 1, 2, 3, 4. Jednak ...

constexpr auto test = generate(); 

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

Jeśli mogę skompilować i uruchomić ten kod za pomocą g ++ 5.2 i -std=c++14, wynik, który jest drukowany na konsoli jest dziwnie, 1032.

Jeśli usunąć constexpr kwalifikatorów więc wykonuje w czasie wykonywania, lub jeśli zamiast pisać jeden z poniższych drobnymi zmianami:

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

... albo ...

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

.. zostanie wydrukowany oczekiwany wynik, 1234. Dodatkowo, clang ++ 3.7.0 wypisuje oczekiwany 1234 we wszystkich przypadkach.

Czy mam trafiony błąd g ++, czy też coś tu brakuje?

Odpowiedz

7

Wygląda on na powiązany z błędem gcc [5 regression] Constant expression factory function initializes std::array with static storage duration strangely i jeśli spróbujemy tego z gcc head live example, to działa dobrze.

raport o błędzie ma następującą podobny przykład, gdy zmienna statyczna sprawa wykazuje podobny problem podczas automatycznego zmienna sprawa nie:

#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 
} 
Powiązane problemy