概要
PHP の ''
や C# の @""
, python の r""
のような、エスケープ記号を省略する文字列定数の書き方は便利ですね。
C++ でも C++11 から文字列定数の仕様が追加されエスケープ記号を省略する書き方ができるようになっていました。 raw string literal と呼ぶようです。
下記リンクの (6) に当たります。
http://en.cppreference.com/w/cpp/language/string_literal
この使い方について解説します。
基本
最もミニマムな書式は
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)";
のように代入できます。
文字列定数の中ではダブルクォート '"'
もエスケープなしで使用できます。
#include <iostream>
int main(void){
std::cout << R"("Hello, World")" << std::endl;
}
"Hello, World"
便利ですねー。
特別な場合
上記の仕様だけでほとんどの場合問題ありませんが、以下のような場合には困ります。
#include <iostream>
int main(void){
// コンパイルエラー!
std::cout << R"("Hello, World(1)")" << std::endl;
}
この例では、 "Hello, World(1
までが raw string literal と解釈されてしまうためコンパイルエラーとなります。文字列定数中に )"
を含んでいてはいけないわけです。
しかしこのようなケースに対処する仕様がしっかり用意されています。
#include <iostream>
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 形式の文字列定数をコンソール出力しています。
#include <iostream>
using namespace std;
int main(void){
cout << u8R"##(<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Hello</title>
</head>
<body>
Hello, World!!!
</body>
</html>
)##";
}
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Hello</title>
</head>
<body>
Hello, World!!!
</body>
</html>