Dies ist eine Art von Follow-up für this topic und befasst sich mit einem kleinen Teil davon. Wie beim vorherigen Thema, lassen Sie uns in Betracht ziehen, dass unser Compiler constexpr
Funktionen für std::initializer_list
und std::array
hat. Lasst uns jetzt direkt zum Punkt kommen.Verwirrung über konstante Ausdrücke
#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;
}
es mit diesem Fehler abstürzt:
error: 'const std::initializer_list<int>{((const int*)(&<anonymous>)), 3u}' is not a constant expression
Auch wenn ich einige Papiere über constexpr
und konstante Ausdrücke inzwischen gelesen, dieses Verhalten macht immer noch keinen Sinn für mich. Wie kommt es, dass das erste Beispiel als ein gültiger konstanter Ausdruck und nicht der zweite betrachtet wird? Ich würde jede Erklärung begrüßen, damit ich danach in Frieden ruhen kann.
HINWEIS: Ich werde genau es sofort, Clang nicht in der Lage sein, den ersten Schnipsel zu kompilieren, da es nicht die constexpr
Bibliothek Ergänzungen nicht implementiert, die für C++ 14 geplant ist. Ich habe GCC 4.7 verwendet.
EDIT: Ok, hier kommt das große Beispiel zu zeigen, was abgelehnt wird und was nicht:
#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;
}
Wie wäre es mit "GCC hat einen Fehler"? :) (Nicht zu sagen, es hat eine, nur eine Möglichkeit.) Und wirklich, Sie sollten in der Lage sein, dies ohne die Zusätze von "constexpr" zu testen, indem Sie Ihre eigenen Analoga schreiben. Und was ist mit constexpr std :: array b = {{a [0], a [1], a [2]}}; '? –
Xeo
Vielleicht [http://ideone.com/56iP0Y] hilft, das Problem einzuschränken –
@ Xeo Was auch immer ich mit Array tun scheint gut zu funktionieren (einschließlich Ihres Beispiels, und Andy mit nur 'std :: arrays' stattdessen von 'std :: initializer_list'). Es scheint, dass das Problem nur mit "std :: initializer_list" zur Kompilierzeit auftritt. Ich habe es nicht geschafft, es ohne "constexpr" oder mit "std :: array" zu reproduzieren. – Morwenn