2015-01-07 9 views
6

Warum funktioniert diese Arbeit:Pass constexpr intializer_list als Argument in C++ 14

constexpr initializer_list<int> ilist = {1,2,3,4}; 
constexpr int my_min = min(ilist); 

Während dies tut:

constexpr int my_min = min({1,2,3,4}); 

ich meinen Code bin stützen auf die constexpr std :: min() -Funktion wie gezeigt here und ich benutze clang3.5.0 zum Compiler (g ++ 4.9.1 scheint nicht bewusst, ein constexpr std :: min()).

Ich kann nicht Sinn der Fehler machen Ich erhalte:

clang35 -stdlib=libc++ -std=c++14 test.cpp -o test; 
test.cpp:158:35: error: constexpr variable 'ilist' must be initialized by a constant expression 
    constexpr initializer_list<int> ilist = {1,2,3,4}; 
           ^  ~~~~~~~~~ 
test.cpp:158:35: note: pointer to subobject of temporary is not a constant expression 
test.cpp:158:43: note: temporary created here 
    constexpr initializer_list<int> ilist = {1,2,3,4}; 
             ^
test.cpp:159:17: error: constexpr variable 'my_min' must be initialized by a constant expression 
    constexpr int my_min = min(ilist); 
       ^  ~~~~~~~~~~ 
test.cpp:159:30: note: initializer of 'ilist' is not a constant expression 
    constexpr int my_min = min(ilist); 
          ^
test.cpp:159:30: note: in call to 'initializer_list(ilist)' 
test.cpp:158:35: note: declared here 
    constexpr initializer_list<int> ilist = {1,2,3,4}; 
+2

Ihre Frage ist ein Duplikat von [this] (https://stackoverflow.com/questions/27496004/why-isnt-stdinitializer-list-defined-as-a-literal-type) (nicht stimmend, um zu schließen, weil der verknüpfte Frage hat keine Antworten). Relevant ist auch [this] (https://groups.google.com/a/isocpp.org/d/topic/std-discussion/aA3BsR4ZuoE/discussion) (verlinkt in den Kommentaren des Betrogenen). – Praetorian

+0

Sie haben Recht, ich habe tatsächlich nicht bemerkt, dass auch nur die Definition von 'constexpr initialiser_list ilist = {1,2,3,4}; 'nicht kompiliert, es sei denn, es ist globale Variable. – dcmm88

+1

Sie können eines der Probleme beheben, indem Sie (das lokale) 'ilist' als' statisch' deklarieren. Die Lebensdauer des temporären Arrays, das zum Implementieren des RHS verwendet wird, wird auf die Dauer des statischen Speichers erweitert, wodurch es möglich wird, seine Adresse innerhalb eines konstanten Ausdrucks zu verwenden. Es behebt jedoch nicht das zweite Problem - und ich bin mir nicht sicher, ob das Absicht oder ein Fehler ist. – dyp

Antwort

2

Der Grund, warum Ihr erstes Snippet nicht im Gegensatz zu dem zweiten kompiliert wird, ist der Zeitpunkt, zu dem das zugrunde liegende Array erstellt wird. [Dcl.init.list]/5:

Ein Objekt des Typs std::initializer_list<E> aus einer Initialisiererliste aufgebaut ist, als wenn die Umsetzung von N Elemente vom Typ const E eine temporären Matrix zugeordnet, in dem N ist die Anzahl der Elemente in der Initialisierungsliste.

Jetzt, wenn wir min aufrufen, greifen wir auf Elemente dieses Arrays zu. Jedoch [expr.const]/7 ist unantastbar:

enter image description here

Keine der Ausnahmen gelten, aber den letzten Aufzählungspunkt beachten Sie das in Ihrem zweiten Beispiel anwendbar ist.

Clang ist (nicht überraschend) korrekt, während GCC fälschlicherweise Ihren Code akzeptiert. Das obige Urteil ist auch der Grund, warum der @ dyp-Code fehlschlägt: Die Ausführung einer l-t-r-Konvertierung unter i ist kein konstanter Ausdruck. Insbesondere gilt (2.7.1) nicht, da das Temporäre nicht const ist.

-2

C 14 ++ ist nicht vollständig umgesetzt noch in keinem der beiden g ++ noch Klirren ++. In Ihrem speziellen Fall: g ++ STL hat template constexpr T min(std::initializer_list ilist); nicht implementiert, während clang ++ constexptr-Konstruktor für initializer_list noch nicht hat.

+0

[C++ 14 Status für GCC] (https://gcc.gnu.org/projects/cxx1y.html). Es sollte mit GCC 5 abgeschlossen werden. – edmz

+1

Das Problem ist, dass 'constexpr initialiser_list ilist = {1,2,3,4}; 'nicht kompilieren kann - nichts über' min' –