2015-09-25 13 views
9

Così ho il seguente semplice frammento:Perché questa funzione di constexpr fornisce risultati diversi in circostanze diverse in 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; 
} 

I contenuti attesi della matrice data nel SquareMatrix<int, 2> prodotto da generate() è 1, 2, 3, 4. Tuttavia ...

constexpr auto test = generate(); 

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

Se compilo ed eseguire questo codice usando g ++ 5.2 e -std=c++14, il risultato che si stampa sulla console è, stranamente, 1032.

Se rimuovere le qualificazioni constexpr quindi entra in fase di esecuzione, o se io invece scrivere uno dei seguenti lievi variazioni:

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

... o ...

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

.. il risultato previsto, 1234, viene stampato. Inoltre, clang ++ 3.7.0 stampa il previsto 1234 in tutti i casi.

Ho colpito un bug g ++ o mi manca qualcosa qui?

risposta

7

Questo sembra relativo al bug gcc [5 regression] Constant expression factory function initializes std::array with static storage duration strangely e se proviamo questo con gcc head live example funziona correttamente.

La segnalazione ha il seguente esempio simile, dove il caso variabile statica presenta un problema simile, mentre il caso variabile automatica non:

#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 
} 
Problemi correlati