constexprでstd :: stringを使用することは可能ですか?


175

C ++ 11、Ubuntu 14.04、GCCデフォルトツールチェーンを使用します

このコードは失敗します:

constexpr std::string constString = "constString";

エラー:constexpr変数 'c​​onstString'のタイプ 'const string {aka const std :: basic_string}'はリテラルではありません... 'std :: basic_string'は自明でないデストラクタを持っているためです

それを使用することが可能であるstd::stringconstexpr?(どうやらそうではない...)もしそうなら、どうやって?で文字列を使用する別の方法はありconstexprますか?


2
std::stringはリテラル型ではありません
Piotr Skotnicki 2014年

7
@PiotrS-問題はそれを言う...
ベクター

4
@Vectorはconstexprの目的を尋ねましたか、なぜstd::stringconstexprになりたいのですか?SOにはいくつかのコンパイル時文字列実装があります。エラーメッセージを理解し、リテラル型のみをconstexprにできることを知っている場合、非リテラル型をconstexprにできるかどうかを尋ねる意味は何ですか?同様に、constexprインスタンスが必要になる理由はいくつかあります。そのため、質問を明確にすることをお勧めします
Piotr Skotnicki 14年

2
はい、@ PiotrSです。とはconstexprいえ、そこには文字列実装があります。std::stringそれらの1つではありません。
テンフォア2014年

3
@PiotrS- SOにはいくつかのコンパイル時文字列実装があります -わかりました、ありがとうございます。それは私にとってオプションではありませんが、私の質問に答えます:std :: stringは機能しません。私がtenfourについて述べたように、私はstd :: stringをそれが機能する方法で使用する方法があるかどうか疑問に思いました。私が気づいていないトリックはたくさんあります。
2014年

回答:


167

いいえ、コンパイラはすでに包括的な説明を提供しています。

しかし、あなたはこれを行うことができます:

constexpr char constString[] = "constString";

実行時に、これを使用してstd::string必要なときにを構築できます。


78
なんでconstexpr auto constString = "constString";?その醜い配列構文を使用する必要はありません;-)
stefan

80
この質問の文脈では、それはより明確です。私のポイントは、選択できる文字列タイプについてです。使用するデータ型を強調しようとしているときchar[]よりも詳細/明確autoです。
tenfour 2014年

7
@tenfourそうですね、それは良い点です。私は時々少しも使用に焦点を当てたと思うよauto;-)
ステファン・

1
ノー@FelixDombekが、C ++ 17であなたが使用できるconstexpr auto s = "c"sv;の導入のためにstring_view
ウィッヒ

6
そのコンテキストでchar配列をconstexprすることは意味がありますか?これを使用して文字列を作成する場合は、とにかくコピーされます。文字列のコンストラクターにリテラルを渡すことと、そのようなconstexpr配列をそれに渡すことの違いは何ですか?
KjMag 2017

167

以下のようC ++ 20はい、。

とおりC ++ 17は、使用することができますstring_view

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

A string_viewはのstringようなオブジェクトであり、charオブジェクトのシーケンスへの不変の非所有参照として機能します。


6
この定数をconst std::string&新しいstd :: string を取る関数に渡すときはいつでも、構築する必要があることに注意してください。これは通常、定数を作成するときに考えていたのとは逆です。したがって、これは良い考えではないと私は言いがちです。少なくともあなたは注意する必要があります。
ランボーラモン

29
@RamboRamon string_viewは暗黙的にに変換できstringないため、誤ってstringからを作成する危険はほとんどありませんstring_view。逆に、char const* 暗黙的にに変換できるstringのでstring_view、この意味では実際に使用する方が安全です。
ジョセフトムソン

4
説明をありがとう。私は完全に同意し、実際にstring_view暗黙的にに変換できないことを忘れましたstring。私が提起した問題はまだ有効ですが、string_view具体的には当てはまりません。実際、あなたが言ったように、それはその点でさらに安全です。
ランボーラモン

5
この回答string_viewが単なるリンクではなく、それが何であるかについてより多くを言っていたら素晴らしいでしょう。
エリック2018

22

C ++ 20はconstexpr文字列とベクトルを追加します

以下の提案が受け入れられている明らかに:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0980r0.pdfと、それはのようなコンストラクタを追加します。

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

すべて/ほとんどのメソッドのconstexprバージョンに加えて。

GCC 9.1.0の時点ではサポートされていません。以下はコンパイルに失敗します。

#include <string>

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

と:

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

エラーあり:

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

std::vectorで議論:constexpr std :: vectorを作成できません

Ubuntu 19.04でテスト済み。


19

問題は重要なデストラクタであるため、デストラクタがから削除されstd::stringconstexpr場合、その型のインスタンスを定義することが可能です。このような

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

18
これはC ++ 17がどのような基本的であるstring_viewことは除いて、あるstring_view機能のほとんどあなたを与えるから、あなたが知っていることstd::string
ウィッヒ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.