web-dev-qa-db-ja.com

上記のリテラルを終了せずに、生の文字列リテラルに) "を含めます

2つの文字)"以下の例では、生の文字列リテラルを終了します。
シーケンス )"がある時点でテキストに表示される可能性があります。このシーケンスがその中にある場合でも、文字列を継続させたいと思います。

R"(  
    Some Text)"  
)";       // ^^

シーケンスを含めるにはどうすればよいですか)"文字列リテラル内で終了せずに?

44
Andreas DM

生の文字列リテラル ほぼ任意の*区切り文字を指定できます。

//choose ### as the delimiter so only )###" ends the string
R"###(  
    Some Text)"  
)###";  

*正確なルールは次のとおりです:「スペース、左括弧(、右括弧)、円記号\、および水平タブ、垂直タブ、フォームフィード、改行を表す制御文字を除く、基本ソース文字セットのすべてのメンバー」 (N3936§2.14.5[Lex.string]文法)および「最大16文字」(§2.14.5/ 2)

69
chris

これは生のリテラルなのでエスケープしても役に立ちませんが、構文はahaのような任意のフレーズを導入することで、開始と終了を明確に区別できるように設計されています。

R"aha(  
    Some Text)"  
)aha";

ちなみに、最後の)"の順序は、例の反対です。


フォーマルについては、一見すると(標準を調べて)、そのままの文字列リテラルでもエスケープが通常のリテラルと同じように機能するように見えるかもしれません。例外がないことがわかっている場合を除いて、ルールに例外が記載されていない場合はどうすれば可能ですか?まあ、生の文字列リテラルがC++ 11で導入されたとき、それは余分なundoing変換フェーズを導入することによるものでした。エスケープ!、つまり、…

C++ 11§2.5/ 3

生の文字列の最初と最後の二重引用符文字の間で、フェーズ1と2で実行された変換(トリグラフ、ユニバーサル文字名、ラインスプライシング)が元に戻ります。この復帰は、d-charr-char、または区切り括弧が識別される前に適用されます。

これは、Unicode文字仕様(\u0042のようなuniversal-character-names)を処理しますが、エスケープのように見えて動作しますが、C++では、エスケープではありませんシーケンス。

真の正式なエスケープは、生の文字列リテラルのコンテンツにカスタムの文法規則を使用することにより、処理される、または処理されません!つまり、C++§2.14.5では、raw-string文法エンティティは次のように定義されます。

"d-char-sequenceopt (r-char-sequenceopt )d-char-sequenceopt "

ここで、r-char-sequencer-charのシーケンスとして定義され、それぞれが

右括弧)の後に最初のd-char-sequenceを除いたソース文字セットの任意のメンバー[上記のahaと同様](空の場合があります)の後に二重引用符を付けます"


本質的に上記は、生の文字列でエスケープを直接使用できないだけでなく(大部分は正であり、負ではない)、Unicode文字仕様を直接使用することもできないことを意味します。

間接的に行う方法は次のとおりです。

#include <iostream>
using namespace std;

auto main() -> int
{
    cout << "Ordinary string with a '\u0042' character.\n";
    cout << R"(Raw string without a '\u0042' character, and no \n either.)" "\n";
    cout << R"(Raw string without a '\u0042' character, i.e. no ')" "\u0042" R"(' character.)" "\n";
}

出力:

「B」文字を含む通常の文字列。つまり、「B」文字はありません。
28

使用できます

R"aaa(  
    Some Text)"  
)aaa"; 

ここでaaaは文字列の区切り文字になります。

3
Pranit Kothari