2014-08-31 8 views
8

Ich schrieb eine constexpr-Funktion, die ein Array zurückgibt.consExpr Array zurückgeben, GCC-Warnung

#include <iostream> 

constexpr auto get_str(void) 
-> const char(&)[4] { 
    return { 'T', 'E', 'S', 'T' }; 
} 

constexpr int sum(const char(&str)[4]){ 
    return str[0] + str[1] + str[2] + str[3]; 
} 

int main(void){ 

    constexpr int s = sum(get_str()); 

    std::cout << s << std::endl; 

    return 0; 
} 

g ++ 4.8 kompiliert den Code richtig, aber gibt die folgende Warnung:

test.cpp: In function ‘constexpr const char (& get_str())[4]’: 
test.cpp:5:30: warning: returning reference to temporary [-Wreturn-local-addr] 
    return { 'T', 'E', 'S', 'T' }; 

ist die Warnung richtig unter diesen Umständen? Ist es inkorrekt, ein Array von einer solchen constexpr-Funktion zurückzugeben, obwohl die Funktion zur Laufzeit eigentlich nie aufgerufen wird, nur während der Kompilierung?

+1

Sie können 'std :: array ', um eine statische Contexpr-Matrix nach Wert zurückzugeben, anstatt eine Referenz zurückzugeben. –

+0

@MikaelPersson Danke, ich habe versucht, std :: array an einem Punkt, aber mein voller Code macht einige seltsame Dinge, die eine Kompilierung-Konvertierung in const char *, und ich konnte nicht tun Arr [0] in einer Konstante Ausdruck. – Xeno

Antwort

2

clang 3.4 nicht diesen Code kompilieren, da sum(get_str()) keinconstexpr ist und soweit ich clang richtig ist hier sagen kann, diese Linie (see it live):

constexpr int s = sum(get_str()); 

die folgende Fehlermeldung erzeugt:

error: constexpr variable 's' must be initialized by a constant expression 
constexpr int s = sum(get_str()); 
      ^ ~~~~~~~~~~~~~~ 

note: read of temporary whose lifetime has ended 
return str[0] + str[1] + str[2] + str[3] 
    ^

Es ist keine gültige constexpr aus zwei Gründen. Das ruft nicht definiertes Verhalten und das ist explicitly disallowed in a constant expression, the draft C++ standard Abschnitt 5.19 sagt zusammenzufassen:

A conditional-expression e is a core constant expression unless the evaluation of e,

und enthält folgende Kugel:

an operation that would have undefined behavior

, die außerhalb seines Lebens sein würde zugreifen. Wir wissen, dass die Lebensdauer des temporären nicht aus dem Abschnitt 12.2Temporäre Objekte in diesem Fall erweitert, die sagt:

The second context is when a reference is bound to a temporary.117 The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except

und enthält folgende Kugel:

The lifetime of a temporary bound to the returned value in a function return statement (6.6.3) is not extended; the temporary is destroyed at the end of the full-expression in the return statement.

Und obwohl es tatsächlich wahr ist, dass ein konstanter Ausdruck ist nicht garantiert, bei der Übersetzung ausgewertet werden, haben wir eine Notiz im Abschnitt 5.19Konstante Ausdrücke, die dies erwähnt (Hervorhebung von mir gehe nach vorn):

Note: Constant expressions can be evaluated during translation.—end note ]

Auch wenn es uns noch erlaubt wäre nicht undefiniertes Verhalten aufzurufen garantiert wurde.

Das zweite Problem ist, dass constexpr Referenzen entweder auf Objekte der statischen Lagerdauer oder Funktionen sein müssen, cppreference erwähnt dies in seinem core constant expression section:

Reference constant expression is an lvalue core constant expression that designates an object with static storage duration or a function

und soweit ich dies in Abschnitt bedeckt sagen kann 5.19Konstante Ausdrücke Absatz die sagt:

each non-static data member of reference type refers to an object with static storage duration or to a function,

1

the function is never actually called at runtime, only during compilation?

garantiert Nicht bei allen Standard. Der Compiler ist gut in der Lage, ihn zur Laufzeit aufzurufen.

constexpr Provisorien sterben nie Wenn der Compiler es zur Kompilierungszeit aufruft. Der Compiler ist nicht verpflichtet.

+0

Es war nicht verpflichtet, aber es war definitiv zur Kompilierzeit, wenn man sich die Baugruppe ansah. Ich denke, die Warnung ist gerechtfertigt, und wenn es nicht garantiert ist, werde ich das vermeiden. – Xeno

+0

Ich weiß, dass das alt ist, aber ich habe das in einer anderen Frage gesehen und es ist hier relevant: "Zusätzlich dazu, Ausdrücke zur Kompilierzeit auswerten zu können, wollen wir in der Lage sein ** zu verlangen, dass Ausdrücke zur Kompilierzeit ausgewertet werden; conetexpr vor einer variablen Definition macht das ** (und impliziert const): – Xeno