概要
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>