1. ホーム
  2. c++

[解決済み] C++11の生文字列リテラルR"(...) "に括弧がある根拠は何ですか?

2023-07-04 14:37:26

質問

C++11で導入された非常に便利な機能で、生の文字列リテラルというものがあります。そして、これを書く代わりに

  regex mask("\\t[0-9]+\\.[0-9]+\\t\\\\SUB");

単純にこう書けばいいんです。

  regex mask(R"(\t[0-9]+\.[0-9]+\t\\SUB)");

かなり読みやすくなりました。しかし、生の文字列リテラルを定義するために、文字列の周りに余分な括弧を置かなければならないことに注意してください。

私の疑問は、なぜこれらが必要なのか、ということです。私にとっては、非常に醜く、非論理的なものに見えます。以下は、私が見た短所です。

  • リテラルをよりコンパクトにするために使用される機能であるにもかかわらず、余分な冗長性がある。
  • リテラルの本体と定義記号を区別するのが難しい

区別がつきにくいというのは、そういうことです。

"good old usual string literal"
 ^-    body inside quotes   -^

R"(new strange raw string literal)"
   ^- body inside parenthesis  -^

そしてこちらがプロ。

  • より柔軟で、生の文字列で利用可能な文字が増え、特にデリミタと一緒に使用した場合。 "delim( can use "()" here )delim"

でもね、もっと柔軟性が必要なら、昔からあるエスケープ可能な文字列リテラルがあるじゃないですか。なぜ標準委員会は、すべての生の文字列リテラルのコンテンツをこれらの絶対に不要な括弧で汚染することを決定したのでしょうか? その背景にはどんな根拠があったのでしょうか?私が言及しなかった長所は何でしょうか?

UPD Kerrekの回答は素晴らしいのですが、残念ながら答えになっていません。私はすでに、それがどのように動作し、どのような利点を与えるかを理解していることを説明しましたので。この質問をしてから5年が経ちますが、未だに答えは出ていません。そして、この決断に、私はまだ苛立っている。これは好みの問題だとも言えるが、私はそうは思わない。スペースはいくつ使うのか、変数の名前はどうするのか、これは SomeFunction() なのか、それとも some_function() - というのは、好みの問題です。そして私は、あるスタイルから別のスタイルへと、実に簡単に切り替えることができるのです。

しかし、これは...。何年経っても不格好で不器用な感じがする。いいえ、これはセンスの問題ではありません。これは、何があってもすべての可能なケースをカバーしたい、ということです。Windows 固有のパス、正規表現、複数行の文字列リテラルを書く必要があるたびに、この醜い括弧を書かなければならない運命にあるのです。そして、何のために?稀に実際に " を文字列で書く必要があるような稀な場合のためか?私は、彼らがこの方法を決定した委員会の会議に出席していたいと思います。そして、この本当に悪い決定には強く反対したいものです。私は願う。今、私たちは絶望的です。

ここまで読んでくださってありがとうございました。これで少しは気が楽になりました。

UPD2 以下は私の代替案で、どちらも既存よりずっと良くなると思います。

提案1. python に触発されました。トリプルクォート付きの文字列リテラルをサポートできない。 R"""Here is a string literal with any content, except for triple quotes, which you don't actually use that often."""

提案2.常識に触発されたもの。現在のものと同様に、すべての可能な文字列リテラルをサポートします。 R"delim"content of string"delim" . 空のデリミタ付き。 R""Looks better, doesn't it?"" . 空の生文字列。 R"""" . 二重引用符で囲まれた生の文字列。 R"#"Here are double quotes: "", thanks"#" .

これらの提案に何か問題はありますか?

どのように解決するのですか?

他の回答で説明されているように、以下のような場合にパースの曖昧さを回避するために、引用符に何か追加する必要があります。 " または )" あるいは、文字列そのものに現れるかもしれない、任意の閉じたシーケンス。

に関しては、まあ、私は構文の選択が 最適でない であることには同意しますが、一般的には OK です ("things could be worse" と考えてもよいでしょう (笑))。私は、これは使用法の単純さと解析の単純さの間の良い妥協点であると思います。

提案1 . pythonにインスパイアされています。トリプルクォーテーションを含む文字列リテラルをサポートしない トリプルクォート

R"""どんな内容でも、トリプルクォート以外は、実際にはそれほど頻繁に使わないものです。

これには確かに問題があります - "実際にはそれほど頻繁に使用しない引用符"。 まず、生の文字列のアイデアは、文字列を表現することです。 文字列。 がありません。 文字列の内容に関係なく、文字列を変更することなく、テキストファイルに表示されるのと同じです。第二に、構文は一般的であるべきで、すなわち "almost raw string" などのバリエーションを追加することなく、である。

この構文で 1 つの引用符をどのように書くのでしょうか。2 つの引用符は?注意 - これらは、特にコードが文字列とパージングを扱っている場合に、非常に一般的なケースです。

提案2 .

R"delim"文字列の内容"delim"です。

R""見栄えが良くなりましたね""。

R"#"Here is double quotes: ""、ありがとうございます"#"。

まあ、こっちの方が候補としてはいいかもしれませんね。しかし、1つだけあります。よくあるケース(そして、それが受け入れられた構文の動機となったと思います)は、ダブルクォート文字そのものが 非常に が一般的で、生の文字列はこのようなケースで便利なはずです。

では、通常の文字列の構文を見てみましょう。

s1 = "\"";
s2 = "\"quoted string\"";

あなたの構文 例: "x"を区切り文字とした場合。

s1 = R"x"""x";
s2 = R"x""quoted string""x";

許容される構文

s1 = R"(")";
s2 = R"("quoted string")";

はい、私は括弧が厄介な視覚効果をもたらすことに同意します。ですから、この構文の作成者は、この場合の追加の "delim" はほとんど必要ないだろう、という考えに基づいていたのではないでしょうか、なぜなら )" が文字列の中に現れることはあまりないからです。しかし、後続引用符、先頭引用符、分離引用符は頻繁に使用されるため、例えば、あなたが提案した構文(#2)では、いくつかの delim が必要になり、その結果、より頻繁に R"".."" から R"delim"..."delim" . というように変更します。

構文がもっと良くなる可能性は?私は個人的には、さらにシンプルな構文のバリエーションを希望します。

Rdelim"string contents"delim;

上記の例で

s1 = Rx"""x; 
s2 = Rx""quoted string""x;

しかし、正しく動作させるためには (現在の文法で可能であれば)、この変形では、文字集合を delim 部分の文字セットを文字/数字のみに制限し (既存の演算子のため)、 おそらく将来の文法との衝突を避けるために最初の文字にさらにいくつかの制限を加える必要があります。

というわけで、より良い選択ができたと信じています。
大幅に この場合、これ以上のことはできませんが。