2016-01-02 3 views
15

Das folgende Programm mit GCC 5.2 kompiliert, aber nicht mit Klirren 3.6:Ist diese Fehlermeldung richtig: Nicht-Typ Template-Argument ist nicht ein konstanter Ausdruck

constexpr bool flag(); 

template <bool b = flag()> 
constexpr bool test() 
{ 
    return b; 
} 

int main() 
{ 
} 

Die Fehlermeldung, die ich mit Klirren bekommen ist:

main.cpp:3:20: error: non-type template argument is not a constant expression 
template <bool b = flag()> 
        ^~~~~~ 
main.cpp:3:20: note: undefined function 'flag' cannot be used in a constant expression 
main.cpp:1:16: note: declared here 
constexpr bool flag(); 
      ^
main.cpp:4:16: error: no return statement in constexpr function 
constexpr bool test() 
      ^

Meine Frage ist: Wer hat Recht? Oder mit anderen Worten: Ist das Programm schlecht formuliert?

+1

Kann dies bestätigen, auch wenn es nicht kling 3.7 kompiliert. Wenn Sie jedoch eine Return-Anweisung in "constexpr bool flag()" schreiben, funktioniert es. – vsoftco

+1

Ich denke, dies bezieht sich auf Ihre andere Frage über den Punkt, wo Standard-Template-Argumente ausgewertet werden: Wenn sie am Definitionspunkt ausgewertet werden, dann kann clang nicht beweisen, dass diese Vorlage unter [temp.res] p8 – dyp

+0

Warum ist Haben Sie eine Rückgabeanweisung in einer void-Funktion? Ich kann auch bestätigen, dass dies auf MSVS 2015 – NathanOliver

Antwort

4

Ich würde sagen, dass Klappern ist richtig:

Aus dem Standard:

[temp.param] 14,1 # 9

9 Ein Standard-Template-Argument ist ein Template-Argument (14.3) nach = in einem Template-Parameter angegeben. [...]

Und [temp.arg.nontype] 14.3.2

1 Ein Template-Argument für einen Nicht-Typen Template-Parameter ist ein umgebauter konstanter Ausdruck (5,20) seine vom Typ des Template-Parameters.

Und [expr.const] 5,20

2 Eine bedingte-Ausdruck e ist ein Kern konstanter Ausdruck, es sei denn die Auswertung von e, nach den Regeln der abstrakten Maschine (1,9), würde man bewerten der folgenden Begriffe:

[...]

(2.3) - ein Aufruf einer undefinierten consExpr-Funktion oder eines undefinierten conexpr-Konstruktors;

Da flag() deklariert, aber nicht definiert ist, ist es kein konstanter Ausdruck und 14.3.2 wird verletzt.

4

Nach ISO C++ 14 Standard-5.19.2:

Ein bedingten Ausdruck e ein Kern konstanter Ausdruck, wenn die Auswertung von e ist, nach den Regeln der abstrakten Maschine (1.9), würde einer der folgenden Ausdrücke bewerten:

  • diese (5.1.1), außer in einer Funktion oder einem constexpr constexpr Konstruktor, der als Teil des E ausgewertet wird;
  • Ein Aufruf einer anderen Funktion als eines consExpr-Konstruktors für eine Literalklasse, eine consExpr-Funktion oder ein impliziter Aufruf eines trivialen Destruktors (12.4) [Hinweis: Überladungsauflösung (13.3) wird wie üblich angewendet - Endnote] ;
  • ein Aufruf einer undefinierten constexpr-Funktion oder eines undefinierten conexpr-Konstruktors;
  • (...) Blockquote

Das Ergebnis jeder constexpr Funktionsaufruf gemacht, bevor es Definition ist nicht ein konstanter Ausdruck.

Schließlich scheint es, dass es GCC-Fehler ist.

+2

Ich denke, alle stimmen darin überein. Es gibt jedoch einige zusätzliche Fragen, die wichtigste ist wahrscheinlich: Darf clang dieses Programm * ablehnen, obwohl das Standard-Template-Argument nie benutzt wird *? – dyp

+0

@ FilipRoséen-refp Ich weiß, dass du damit für deine Smeta-Techniken umgehen musstest, aber ich kann mich nicht erinnern, woher diese Informationen stammen. Ist es aus einem Entwurf, einer Diskussion, einem Fehlerbericht, ..? – dyp

+0

@dyp Ich bin mir ziemlich sicher, dass ich die jeweilige Formulierung in einem der Beiträge unter http://b.atch.se anspreche - ich bin gerade in der U-Bahn, kann aber Details zum Thema (einschließlich einer Antwort) angeben, wenn ich nach Hause kommen (hoffentlich). –

Verwandte Themen