web-dev-qa-db-fra.com

Est-il possible d'utiliser std :: string dans un constexpr?

tilisation de C++ 11, Ubuntu 14.04, chaîne d'outils par défaut de GCC.

Ce code échoue:

constexpr std::string constString = "constString";

error: le type 'const string {aka const std :: basic_string}' de la variable constexpr 'constString' n'est pas littéral ... car ... 'std :: basic_string' a un destructeur non trivial

Est-il possible d'utiliser std::string dans aconstexpr? (apparemment pas ...) Si oui, comment? Existe-t-il un autre moyen d'utiliser une chaîne de caractères dans un constexpr?

132
Vector

Non, et votre compilateur vous a déjà fourni une explication complète.

Mais vous pouvez faire ceci:

constexpr char constString[] = "constString";

Au moment de l'exécution, cela peut être utilisé pour construire un std::string lorsque cela est nécessaire.

130
tenfour

En C++ 17, vous pouvez utiliser string_view :

_constexpr std::string_view sv = "hello, world";
_

Un _string_view_ est un objet de type string qui agit comme une référence immuable et non propriétaire de toute séquence d'objets char.

103
Joseph Thomson

Comme le problème est lié au destructeur non trivial, il est donc possible de définir une instance constexpr de ce type si le destructeur est supprimé du std::string. Comme ça

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;
}
16
neuront

C++ 20 ajoutera constexpr chaînes et vecteurs

La proposition suivante a été acceptée apparemment: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0980r0.pdf et il ajoute des constructeurs tels que:

// 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;

en plus des versions constexpr de toutes/la plupart des méthodes.

Il n'y a pas de support à partir de GCC 9.1.0, la compilation suivante échoue:

#include <string>

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

avec:

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

avec erreur:

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

std::vector discuté à: Impossible de créer constexpr std :: vector

Testé dans Ubuntu 19.04.