--- title: C++ でも PHP のヒアドキュメント的なことができる (raw string literal) tags: C++ author: _meki slide: false --- # 概要 PHP の `''` や C# の `@""`, python の `r""` のような、エスケープ記号を省略する文字列定数の書き方は便利ですね。 C++ でも C++11 から文字列定数の仕様が追加されエスケープ記号を省略する書き方ができるようになっていました。 raw string literal と呼ぶようです。 下記リンクの (6) に当たります。 http://en.cppreference.com/w/cpp/language/string_literal この使い方について解説します。 # 基本 最もミニマムな書式は ```cpp const char str[] = R"([ここに文字列定数])"; ``` です。先頭のダブルクォートの前に `'R'` をつけ、文字列定数の前後を `'('` と `')'` で囲みます。 例えば Windows のパス文字列 `C:\path\to\folder\file.txt` のようなものを const char に代入したいと思ったとき、従来は ``` const char str[] = "C:\\path\\to\\folder\\file.txt"; ``` と書いていたのを、 ``` const char str[] = R"(C:\path\to\folder\file.txt)"; ``` のように代入できます。 文字列定数の中ではダブルクォート `'"'` もエスケープなしで使用できます。 ```cpp #include int main(void){ std::cout << R"("Hello, World")" << std::endl; } ``` ```:出力 "Hello, World" ``` 便利ですねー。 # 特別な場合 上記の仕様だけでほとんどの場合問題ありませんが、以下のような場合には困ります。 ```cpp #include int main(void){ // コンパイルエラー! std::cout << R"("Hello, World(1)")" << std::endl; } ``` この例では、 `"Hello, World(1` までが raw string literal と解釈されてしまうためコンパイルエラーとなります。文字列定数中に `)"` を含んでいてはいけないわけです。 しかしこのようなケースに対処する仕様がしっかり用意されています。 ```cpp #include int main(void){ // OK! std::cout << R"#("Hello, World(1)")#" << std::endl; } ``` のように、 `R"` と `(` の間に任意の文字列(*)を付け足して開始・終了パターンを変更することができます。 (*) `(`, `)`, `\`, ` ` を除いた英数字。最大 16 字まで # 他の書式との組み合わせ raw string literal は他の文字列定数書式と組み合わせることができます。 - `R("...")` で `const char[ ]`. - `LR("...)"` で `const wchar_t[ ]`. - `u8R("...)"` で `const char[ ]` (UTF-8). - `uR("...)"` で `const char16_t[ ]` (UTF-16). - `UR("...)"` で `const char32_t[ ]` (UTF-32). 下例では UTF-8 形式の文字列定数をコンソール出力しています。 ```cpp:main.cpp #include using namespace std; int main(void){ cout << u8R"##( Hello Hello, World!!! )##"; } ``` ```:出力 Hello Hello, World!!! ```