2008-12-07

Raw string Literalについて

去る12月5日のC++WGのアドホック会議で、誰もRaw String Literalの正しい知識を持っていなかったので、ここに正しい内容を書き記す。かく言う私自身も、Raw String Literalについてはまったくもって不勉強であった。というのも、名前が指し示す通りの意味でしかないではないかと思っていたのだ。つまり、改行やバックスラッシュの類もすべてそのまま記述できるリテラルだと思っていた。しかしこれは誤りである。

まず、通常の文字列リテラルでは、一部の文字が特殊な意味を表すので使えない。例えば、

"\\" ; // バックスラッシュひとつ
"\n" ; // 改行コード
""" ; // エラー

これらを何とかしたい。そこで、Raw String Literalが考え出された。

この文字列の解説は簡単にはいかない。まず、通常の文字列リテラルの前にRがつく。文字列の中身は以下のようになる。

" d-char-sequenceopt [ r-char-sequenceopt ] d-char-sequenceopt "

まず、最初と最後のd-char-sequenceとは、連続したひとつ以上のd-charである。これは省略できる。d-charとは何か。それは、空白、[、 ]、 垂直タブ、水平タブ、フォームフィード、改行、を除く、basic source character setである。つまり、2.2.1で定義されている96文字の内の、89文字のことだ。アルファベットと数字と[]以外の記号である。

つぎに、[]で文字列を囲む。その中には、r-char-sequenceを記述する。r-char-sequenceとは、ひとつ以上のr-charである。r-charとは何か。それはほとんどすべての文字である。何でもいい。ただし、いくつか例外がある。

まず、\u、\Uは使えない。これはユニバーサルキャラクタ名を記述するために必要だからである。それと、最後のd-char-sequenceに続く]が使えない。それ以外は普通に使える。

R"[]]"

この場合では、最後の]が、最初の[を閉じるために使われる、したがって実際の文字列は

"]"

である。それ以外は、なんでも自由に使える。

R"[ここにはほとんど何でも記述できる。]" ;

R"[\でも使えるのは楽だ。\rや\nや\tなどもそのまま記述できる。ただし、uもしくはUが続く場合は使えない。]"

R"[たとえば、
このように
改行も記述できるってゆーか
そんなの
あたりまえだし
この場合
改行が
たくさんあって
読みやすいし]" ;

これは、従来の文字列リテラルでは、次のようになる。

"ここにはほとんど何でも記述できる。"

"\でも使えるのは楽だ。\\rや\\nや\\tなどもそのまま記述できる。ただし、uもしくはUが続く場合は使えない。"

"たとえば、\nこのように\n改行も記述できるってゆーか\nそんなの\nあたりまえだし\nこの場合\n改行が\nたくさんあって\n読みやすいし"

という文字列になる。

どうもドラフトの記述がよくわからない。2.13.4 String literalsのパラグラフ3のサンサンプルコード

the assert will succeed:
const char *p = R"[a
b
c]";
assert(std::strcmp(p, "ab\nc") == 0);

となっているが。pの指す文字列は、"a\nb\nc"である。assert will succeedというのは、assertされるということなのだろうか。それならpの指し示す内容は"ab\nc"でなければ何でもいいことになり、サンプルコードとして変だと思うのだが、いいのだろうか。

それから、Raw String Literalの中の、[]は省略できないように読めるのだが、ドラフトのサンプルの中では省略しているものがある。いいのだろうか。

d-char-sequenceの目的がさっぱり分からないので除外。ドラフトからでは、前後のd-char-sequenceは同じ文字の並びでなければならない。最大で16文字である。ということしか分からない。

5 comments:

Anonymous said...

assert will succeedは、評価式がtrueになり、実行が継続する
すなわちassertion failedにはならないってことだと思います。

江添亮 said...

ですよね。
ドラフトのサンプルコードでは、assert内の式は0ではないので、assertされます。
だいたいassertされることに成功するというのは変ですよね。このサンプルコード的にも。

Anonymous said...

お疲れ様でした.朝最初にお会いした梶本です.

会議の後にharu-sさんとお話して,帰宅後にドラフトを読み直してみたのですが,2.13.4 ¶2に,
A string literal that has an R in the prefix is a raw string literal. The terminating d-char-sequence of a raw-string is the same sequence of characters as the initial d-char-sequence.
とあるので,上記の例のR"abc[]]123"は,R"abc[]]abc"かR"123[]]123"じゃないと駄目なんじゃないですかね.
で,さらに2.13.4 ¶2のas inの後の,u8R"**[...]**"やuR"*~[...]*~"やUR"zzz[...]zzz"などから,d-char-sequenceは実際の文字列には含まれない気がします.
したがって,R"abc[]]abc"は"]"と同じになるんじゃないかと.
そしてr-char-sequenceの中に]abcみたいなものが出てくるなら,d-char-sequenceの方を変更してくれという意図なのではないでしょうか.

Anonymous said...

http://d.hatena.ne.jp/haru-s/20081205
haru-sさんもエントリ書いておられました.

江添亮 said...

どうやらd-char-sequenceは前後同じになりそうですね。
ただ、[]を識別するものとして機能するというのは疑問です。
d-char-sequenceが無ければ識別できないものでもないでしょう。