Globale String-Literale korrekt mit constexpr definieren



  • Hiho,

    in old school C++ konntem an String-Literale ja folgender Maßen in einer Headerdatei deklarieren:

    extern const wchar_t* fileReadError = L"Could not read the xml file";
    

    und entsprechend in der cpp dann definieren und woanders nutzen.
    Ich wollte das nun auf constexpr umstellen und hatte dazu bisher die CPP gelöscht, und im Header folgendes geschrieben

    constexpr wchar_t* fileReadError = L"Could not read the xml file";
    

    In meinem alten Projekt funktioniert das auch wunderbar und klappt. In einem neueren fliegt jetzt jedoch eine Fehlermeldung: *error C2440: "Initialisierung": "const wchar_t [9]" kann nicht in "wchar_t const " konvertiert werden

    Darauf hin habe ich geschaut, wie für C++11/17 die Empfehlung ist , bin da jedoch nicht recht schlau draus geworden. Oft wird noch mit static gearbeitet, einige nutzen ein char-Array anstatt des Zeigers, andere string_view.

    Daher meine Frage: ist das oben überhaupt korrekt (oder kompiliert das VS mal wieder etwas, was eigentlich einen Fehler werfen sollte) und wenn es falsch sein sollte: wie ist die korrekte Nutzung von constexpr für diesen Anwendungsfall?

    VG

    Pellaeon



  • Warum nicht std::string ?
    Damit würdest du warscheinlich sämtliche Probleme vermeiden.



  • axels. schrieb:

    Warum nicht std::string ?

    Ein std::string kann niemals as constexpr deklariert werden, da std::string einen nicht trivialen Konstruktor hat.

    Pellaeon schrieb:

    In meinem alten Projekt funktioniert das auch wunderbar und klappt. In einem neueren fliegt jetzt jedoch eine Fehlermeldung: *error C2440: "Initialisierung": "const wchar_t [9]" kann nicht in "wchar_t const " konvertiert werden

    Naja, die Fehlermeldung sagts doch ganz klar?

    constexpr auto fileReadError = L"Could not read the xml file";
    

    ftw.



  • Swordfish schrieb:

    Naja, die Fehlermeldung sagts doch ganz klar?

    constexpr auto fileReadError = L"Could not read the xml file";
    

    ftw.

    D. h. constexpr wchar_t* ist falsch? Weil ich habe ein Projekt, da kompiliert es und eines, da wirft er mir den obigen Fehler. Daher meien Frage, welches Verhalten das Richtige ist.



  • wchar_t const * als Typ sollte auch passen.



  • Und die Verwirrung aufzulösen: constexpr ersetzt hier nicht const .
    Man kann sehr wohl constexpr const pointertyp * name = ... schreiben.

    Das constexpr bezieht sich auf das, was zurückgegeben wird - nicht auf das, worauf das zurückgegebene zeigt.


  • Mod

    Pellaeon schrieb:

    in old school C++ konntem an String-Literale ja folgender Maßen in einer Headerdatei deklarieren:

    extern const wchar_t* fileReadError = L"Could not read the xml file";
    

    und entsprechend in der cpp dann definieren und woanders nutzen.

    Dein Code ist allerdings eine Definition 😉

    Pellaeon schrieb:

    Ich wollte das nun auf constexpr umstellen und hatte dazu bisher die CPP gelöscht, und im Header folgendes geschrieben

    constexpr wchar_t* fileReadError = L"Could not read the xml file";
    

    constexpr ist kein type specifier.
    D.h. constexpr an sich modifiziert nicht einen Typ als solchen, sondern kann nur in Deklarationen eingesetzt werden und modifiziert den Typ der Entität, die deklariert wird, indem diese dann top-level const-qualifiziert ist.
    Der deklarierte Typ ist hier wchar_t* und constexpr modifiziert dies zu wchar_t* const.

    Abgesehen davon, das die Änderung zu constexpr (wenn korrekt durchgeführt) keinerlei positive Auswirkung hat, wäre ein Modernisierung eher in der Verwendung von auto zu sehen, schliesslich kennt das Literal sein eigen Typ bereits.

    constexpr auto fileReadError = L"Could not read the xml file";
    

    Nachteilig dabei ist aber, dass potentiell jede Übersetzungseinheit, die diesen String benutzt, eine eigene Kopie des Literals hat. const impliziert internal linkage - der old school Code hat dieses Problem nicht.

    Mit C++17 können wir hingegen inline im Header einsetzen, vermeiden so unnötige Kopien und können ganz nebenbei noch Typinformationen (Länge) erhalten:

    constexpr inline wchar_t fileReadError[] = L"Could not read the xml file";
    

    (inline geht vor const in Bezug auf Linkage).



  • Danke für die Antworten! 👍


Log in to reply