Ist es möglich, std :: string in einem constexpr zu verwenden?

175

Unter Verwendung von C ++ 11, Ubuntu 14.04, GCC Standard-Toolchain .

Dieser Code schlägt fehl:

constexpr std::string constString = "constString";

Fehler: Der Typ 'const string {aka const std :: basic_string}' der constexpr-Variablen 'constString' ist nicht wörtlich ... weil ... 'std :: basic_string' einen nicht trivialen Destruktor hat

Ist es möglich, std::stringin einem zu verwenden constexpr? (anscheinend nicht ...) Wenn ja, wie? Gibt es eine alternative Möglichkeit, eine Zeichenfolge in a zu verwenden constexpr?

Vektor
quelle
2
std::stringist kein wörtlicher Typ
Piotr Skotnicki
7
@PiotrS - die Frage sagt, dass ...
Vector
4
@Vector habe ich dich gefragt, wofür der constexpr ist oder warum du std::stringconstexpr sein willst? Auf SO gibt es mehrere Implementierungen von Zeichenfolgen zur Kompilierungszeit. Was bringt es, zu fragen, ob Sie einen nicht-wörtlichen Typ constexpr erstellen können, wenn Sie die Fehlermeldung verstehen und wissen, dass nur wörtliche Typen constexpr erstellt werden können? Es gibt auch mehrere Gründe, warum man eine constexpr-Instanz haben möchte, daher schlage ich vor, dass Sie Ihre Frage klären
Piotr Skotnicki
2
Ja als @PiotrS. sagte, es gibt constexprString-Implementierungen da draußen. std::stringist keiner von ihnen.
vierundvierzig
3
@PiotrS - Es gibt mehrere Implementierungen von Zeichenfolgen zur Kompilierungszeit auf SO - OK, danke, verstanden. Das ist keine Option für mich, aber es beantwortet meine Frage: Auf keinen Fall wird std :: string funktionieren. Wie ich zu Tenfour bemerkte, fragte ich mich, ob es eine Möglichkeit gibt, std :: string so zu verwenden, dass es funktioniert. Es gibt viele Tricks, die mir sicherlich nicht bewusst sind.
Vektor

Antworten:

167

Nein, und Ihr Compiler hat Ihnen bereits eine umfassende Erklärung gegeben.

Aber Sie könnten dies tun:

constexpr char constString[] = "constString";

Zur Laufzeit kann dies verwendet werden, um std::stringbei Bedarf eine zu erstellen .

zehn vier
quelle
78
Warum nicht constexpr auto constString = "constString";? Keine Notwendigkeit, diese hässliche Array-Syntax zu verwenden ;-)
Stefan
80
Im Zusammenhang mit dieser Frage ist es klarer. Mein Punkt ist, aus welchen Zeichenfolgentypen Sie auswählen können. char[]ist ausführlicher / klarer als autowenn ich versuche, den zu verwendenden Datentyp hervorzuheben.
vierundvierzig
7
@tenfour Richtig, das ist ein guter Punkt. Ich denke, ich bin manchmal etwas zu konzentriert auf die Verwendung von auto;-)
Stefan
1
@FelixDombek nein, aber mit c ++ 17 könnten Sie constexpr auto s = "c"sv;aufgrund der Einführung vonstring_view
Weicht
6
Ist es sinnvoll, in diesem Zusammenhang ein char-Array zu steuern? Wenn Sie damit einen String erstellen, wird dieser trotzdem kopiert. Was ist der Unterschied zwischen der Übergabe eines Literals an den Konstruktor der Zeichenfolge und der Übergabe eines solchen constexpr-Arrays an diesen?
KjMag
167

Ab C ++ 20 ja.

Ab C ++ 17 können Sie Folgendes verwenden string_view:

constexpr std::string_view sv = "hello, world";

A string_viewist ein stringähnliches Objekt, das als unveränderlicher, nicht besitzender Verweis auf eine beliebige Folge von charObjekten fungiert.

Joseph Thomson
quelle
6
Beachten Sie, dass jedes Mal, wenn Sie diese Konstante an eine Funktion übergeben, die const std::string&einen neuen std :: string erstellt, erstellt werden muss. Das ist normalerweise das Gegenteil von dem, was man beim Erstellen einer Konstante im Sinn hatte. Daher neige ich dazu zu sagen, dass dies keine gute Idee ist. Zumindest muss man vorsichtig sein.
Rambo Ramon
29
@RamboRamon string_viewist nicht implizit in konvertierbar string, daher besteht nur eine geringe Gefahr, dass versehentlich ein stringaus einem erstellt wird string_view. Umgekehrt char const* ist implizit konvertierbar in string, so dass die Verwendung string_viewin diesem Sinne tatsächlich sicherer ist.
Joseph Thomson
4
Danke für die Klarstellung. Ich stimme vollkommen zu und habe tatsächlich vergessen, dass dies string_viewnicht implizit konvertierbar ist string. IMO ist das Problem, das ich angesprochen habe, immer noch gültig, gilt aber nicht string_viewspeziell für. Wie Sie bereits erwähnt haben, ist dies in dieser Hinsicht sogar noch sicherer.
Rambo Ramon
5
Es wäre großartig, wenn diese Antwort mehr darüber aussagen würde, was string_viewist, anstatt nur einen Link.
Eric
22

C ++ 20 fügt constexprZeichenfolgen und Vektoren hinzu

Der folgende Vorschlag wurde anscheinend angenommen : http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0980r0.pdf und fügt Konstruktoren hinzu, wie:

// 20.3.2.2, construct/copy/destroy
constexpr
basic_string() noexcept(noexcept(Allocator())) : basic_string(Allocator()) { }
constexpr
explicit basic_string(const Allocator& a) noexcept;
constexpr
basic_string(const basic_string& str);
constexpr
basic_string(basic_string&& str) noexcept;

zusätzlich zu constexpr Versionen aller / der meisten Methoden.

Ab GCC 9.1.0 gibt es keine Unterstützung. Folgendes kann nicht kompiliert werden:

#include <string>

int main() {
    constexpr std::string s("abc");
}

mit:

g++-9 -std=c++2a main.cpp

mit Fehler:

error: the type const string {aka const std::__cxx11::basic_string<char>’} of constexpr variable s is not literal

std::vectordiskutiert unter: constexpr std :: vector kann nicht erstellt werden

Getestet in Ubuntu 19.04.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
quelle
19

Da das Problem der nicht triviale Destruktor ist std::string, kann eine constexprInstanz dieses Typs definiert werden , wenn der Destruktor aus dem entfernt wird . So was

struct constexpr_str {
    char const* str;
    std::size_t size;

    // can only construct from a char[] literal
    template <std::size_t N>
    constexpr constexpr_str(char const (&s)[N])
        : str(s)
        , size(N - 1) // not count the trailing nul
    {}
};

int main()
{
    constexpr constexpr_str s("constString");

    // its .size is a constexpr
    std::array<int, s.size> a;
    return 0;
}
Neuront
quelle
18
Dies ist im Grunde , was c ++ 17 string_viewist, mit der Ausnahme , dass string_viewSie die meisten Funktionen gibt , dass Sie wissen ausstd::string
Wich