Questa è una sorta di follow-up per this topic e tratta di una piccola parte di esso. Come per l'argomento precedente, consideriamo che il nostro compilatore ha le funzioni constexpr
per std::initializer_list
e std::array
. Ora, andiamo direttamente al punto.Confusione sulle espressioni costanti
#include <array>
#include <initializer_list>
int main()
{
constexpr std::array<int, 3> a = {{ 1, 2, 3 }};
constexpr int a0 = a[0];
constexpr int a1 = a[1];
constexpr int a2 = a[2];
constexpr std::initializer_list<int> b = { a0, a1, a2 };
return 0;
}
#include <array>
#include <initializer_list>
int main()
{
constexpr std::array<int, 3> a = {{ 1, 2, 3 }};
constexpr std::initializer_list<int> b = { a[0], a[1], a[2] };
return 0;
}
Si blocca con questo errore:
error: 'const std::initializer_list<int>{((const int*)(&<anonymous>)), 3u}' is not a constant expression
Anche se ho letto alcuni giornali circa constexpr
e costanti espressioni nel frattempo, questo comportamento non ha ancora senso per me. Come mai il primo esempio è considerato un'espressione costante valida e non la seconda? Gradirei qualsiasi spiegazione in modo da poter riposare in pace dopo.
NOTA: io precisa subito, Clang non sarò in grado di compilare il primo frammento di quanto non attuare le constexpr
aggiunte di libreria che sono previste per C++ 14. Ho usato GCC 4.7.
EDIT: Ok, ecco che arriva il grande esempio per mostrare ciò che viene respinto e ciò che non è:
#include <array>
#include <initializer_list>
constexpr int foo = 42;
constexpr int bar() { return foo; }
struct eggs { int a, b; };
int main()
{
constexpr std::array<int, 3> a = {{ 1, 2, 3 }};
constexpr int a0 = a[0];
constexpr int a1 = a[1];
constexpr int a2 = a[2];
// From Xeo and Andy tests
constexpr std::array<int, 1> a = { bar() }; // OK
constexpr std::array<int, 3> b = {{ a[0], a[1], a[2] }}; // OK
std::initializer_list<int> b = { a[0], a[1], a[2] }; // OK
constexpr std::initializer_list<int> b = { a0, a1, a2 }; // OK
constexpr std::initializer_list<int> b = { foo }; // OK
constexpr std::initializer_list<int> c = { bar() }; // ERROR
constexpr std::initializer_list<int> b = { a[0], a[1], a[2] }; // ERROR
// From Matheus Izvekov and Daniel Krügler
constexpr eggs good = { 1, 2 }; // OK
constexpr std::initializer_list<eggs> bad = { { 1, 2 }, { 3, 4 } }; // ERROR
constexpr std::initializer_list<eggs> bad2 = { good, good }; // ERROR
return 0;
}
Che ne dici di "GCC ha un bug"? :) (Non dicendo che ne abbia una, solo una possibilità.) E davvero, dovresti essere in grado di testare questo senza le aggiunte di 'constexpr' scrivendo i tuoi stessi analoghi. Inoltre, per quanto riguarda 'constexpr std :: array b = {{a [0], a [1], a [2]}};'? –
Xeo
Forse [questo] (http://ideone.com/56iP0Y) aiuta a restringere il problema –
@Xeo Qualsiasi cosa io faccia con array sembra funzionare bene (incluso il tuo esempio, e quelli di Andy con solo 'std :: array' invece di 'std :: initializer_list'). Sembra che il problema si verifica solo con 'std :: initializer_list' in fase di compilazione. Non sono riuscito a riprodurlo senza 'constexpr' o con' std :: array'. – Morwenn