2015-03-04 6 views
14

Es scheint offensichtlich, dass constexpr const impliziert und somit ist es üblich, um zu sehen:consExpr const vs constexpr Variablen?

constexpr int foo = 42; // no const here 

Allerdings, wenn Sie schreiben:

constexpr char *const str = "foo"; 

Dann wird GCC laichen „Warnung: veraltet Konvertierung von String-Konstante ' char * '"wenn -Write-String-Flag übergeben wird.

Schreiben:

constexpr const char *const str = "foo"; 

löst das Problem.

Sind also constexpr const und constexpr wirklich gleich?

Antwort

24

Das Problem ist, dass in einer Variablendeklaration, constexpr immer gilt die const -ness auf das Objekt deklariert; const auf der anderen Seite kann auf einen anderen Typ, abhängig von der Platzierung gelten.

So

constexpr const int i = 3; 
constexpr int i = 3; 

äquivalent sind;

constexpr char* p = nullptr; 
constexpr char* const p = nullptr; 

sind gleichwertig; beide machen einen const Zeiger auf char.

constexpr const char* p = nullptr; 
constexpr const char* const p = nullptr; 

sind gleichwertig. constexpr macht ein const Zeiger. Die const in const char * macht Punkt auf const char.

1

Die Fehlermeldung, die Sie sehen, hat nichts mit dem Schlüsselwort constexpr per se zu tun.

A Stringliteral wie "foo", wie es in:

somefunction("foo"); 

Der Typ dieser Zeichenkette ist const char *. Die folgende Anweisung:

char *const str = "foo"; 

Dieser versucht einen const char * Wert auf einen char * Wert zuzuweisen. Der sich ergebende char * Wert ist nicht veränderbar, konstant, aber zu diesem Zeitpunkt ist der Fehler bereits aufgetreten: ein Versuch, einen const char * in einen char * umzuwandeln. Das Schlüsselwort in Ihrem Beispiel ist nur eine Ablenkung und hat keinen Einfluss auf den Fehler

+0

Obwohl wahr, ich denke, das OP ist richtig, es _ought_ auf den Fehler haben. "conetexpr" und "consExpr const" sollten identisch sein. –

+1

Das Problem ist die Umwandlung eines const char * in ein char *. Ob der resultierende Wert ein const oder ein conexpr ist, ist kein Faktor. Der Fehler ist bereits an diesem Punkt aufgetreten. Derselbe Fehler tritt nur bei einem einfachen Zeichen * foo = "bar" auf. –

+2

Der Typ von '" foo "' ist 'const char [4]'. –

-1

Nein. Zu sagen, sie sind das gleiche bedeutet, dass es keine Zeit gibt, die nicht mit const gültig wäre, ohne funktionell identischen Code zu einer const-Version zu erzeugen.

Ich finde dies nützlich bei der Erstellung von sicheren Singletons. Ich habe das nicht vollständig untersucht und würde erwarten, dass es andere gültige Verwendungen für nicht-consterexpr gibt.

Als Beispiel hier ist der Code, dass nicht-const constexpr erfordert:

Beginnen Sie mit einer globalen Definition einer Variablen:

int global_int_; 

Und jetzt können wir eine constexpr Funktion erstellen, die zurückgibt ein Hinweis darauf:

constexpr int& get_global() 
{ 
    return global_int_; 
} 

Jetzt können wir woanders mit dieser Referenz:

int main() 
{ 
    constexpr int& i{ get_global() }; 
    // do stuff with i 
    return 0; 
} 

Wir können jetzt i als nicht-const int verwenden. Wenn const impliziert wäre, wäre dies nicht möglich.

Da non-const constexpr gültig ist, müssen Sie, wenn Sie einen constexpr verwenden, der const sein muss, dies explizit deklarieren.

+2

Dies ist eine komplette Hering. Das C++ 14 conexpr-not-implicitly-const ist für Member-Funktionen. –

+0

@ T.C. Ich habe ein Beispiel für non-const consxpr ohne eine Memberfunktion gegeben, also bin ich mir nicht sicher, was Sie meinen. –

+1

Das hat nichts mit der C++ 14 Änderung zu tun. Genau wie bei Zeigern wird der "constexpr" auf die Referenz selbst angewendet (was ein No-Op ist, da Referenzen nicht geändert werden können) und nicht auf das Objekt, auf das Bezug genommen wird. –