User-defined literals (since C++11)
ユーザー定義の接尾辞を定義することで、整数、浮動小数点、文字、および文字列リテラルがユーザー定義型のオブジェクトを生成できるようにします。
目次 |
構文
ユーザー定義リテラルは、以下のいずれかの形式の式です
| decimal-literal ud-suffix | (1) | ||||||||
| octal-literal ud-suffix | (2) | ||||||||
| hex-literal ud-suffix | (3) | ||||||||
| binary-literal ud-suffix | (4) | ||||||||
| fractional-constant exponent-part (optional) ud-suffix | (5) | ||||||||
| digit-sequence exponent-part ud-suffix | (6) | ||||||||
| character-literal ud-suffix | (7) | ||||||||
| string-literal ud-suffix | (8) | ||||||||
| decimal-literal | - | 整数リテラル と同じ、非ゼロの10進数字の後に0個以上の10進数字が続くもの |
| octal-literal | - | 整数リテラル と同じ、ゼロの後に0個以上の8進数字が続くもの |
| hex-literal | - |
整数リテラル
と同じ、
0x
または
0X
の後に1個以上の16進数字が続くもの
|
| binary-literal | - |
整数リテラル
と同じ、
0b
または
0B
の後に1個以上の2進数字が続くもの
|
| digit-sequence | - | 浮動小数点リテラル と同じ、10進数字の並び |
| fractional-constant | - | 浮動小数点リテラル と同じ、 digit-sequence の後にドット( 123 . )が続くもの、またはオプションの digit-sequence の後にドットと別の digit-sequence が続くもの( 1.0 または .12 ) |
| exponent-part | - |
浮動小数点リテラル
と同じ、文字
e
または文字
E
の後にオプションの符号と
digit-sequence
が続くもの
|
| character-literal | - | 文字リテラル と同じ |
| string-literal | - | 文字列リテラル と同じ、raw文字列リテラルを含む |
| ud-suffix | - | 識別子、 リテラル演算子 または リテラル演算子テンプレート 宣言によって導入される( 下記 を参照) |
|
整数リテラル
および
浮動小数点リテラル
の数字シーケンスにおいて、任意の2つの数字の間に区切り文字
|
(C++14以降) |
トークンがユーザー定義リテラル構文と通常のリテラル構文の両方に一致する場合、それは通常のリテラルであると見なされます(つまり、
LL
を
123LL
でオーバーロードすることは不可能です)。
コンパイラがユーザー定義リテラルに
ud-suffix
X
が付いたものを検出すると、
非修飾名前探索
を実行し、
operator
""
X
という名前の関数を探します。探索が宣言を見つけられない場合、プログラムは不適格となります。それ以外の場合、
|
a)
オーバーロード集合が、文字列リテラル演算子テンプレートを含み、そのテンプレートパラメータが定数であり、
str
が適切なテンプレート引数である場合、ユーザー定義リテラル式は関数呼び出し
operator
""
X
<
str
>
(
)
として扱われる;
|
(C++20以降) |
long double operator ""_w(long double); std::string operator ""_w(const char16_t*, size_t); unsigned operator ""_w(const char*); int main() { 1.2_w; // operator ""_w(1.2L) を呼び出す u"one"_w; // operator ""_w(u"one", 3) を呼び出す 12_w; // operator ""_w("12") を呼び出す "two"_w; // エラー: 適用可能なリテラル演算子が存在しない }
文字列リテラルの連結が 翻訳フェーズ6 で行われる際、ユーザー定義文字列リテラルも連結され、その ud-suffix は連結の目的では無視されます。ただし、連結されたすべてのリテラルに現れるサフィックスは1つのみである必要があります:
int main() { L"A" "B" "C"_x; // OK: L"ABC"_x と同じ "P"_x "Q" "R"_y; // エラー: 2つの異なるユーザー定義サフィックス (_x と _y) }
リテラル演算子
ユーザー定義リテラルによって呼び出される関数は、 literal operator (または、テンプレートである場合は literal operator template )として知られています。これは他の function や function template と同様に名前空間スコープで宣言されます(friend関数、関数テンプレートの明示的なインスタンス化または特殊化、using宣言によって導入されることもあります)。ただし、以下の制限が適用されます:
この関数の名前は、次の2つの形式のいずれかを取ることができます:
operator ""
identifier
|
(1) | (非推奨) | |||||||
operator
user-defined-string-literal
|
(2) | ||||||||
| identifier | - | この関数を呼び出すユーザー定義リテラルの ud-suffix として使用する identifier |
| user-defined-string-literal | - |
文字シーケンス
""
に続けて(スペースなしで)記述され、
ud-suffix
となる文字シーケンス
|
ud-suffix
はアンダースコア
_
で始まらなければなりません:アンダースコアで始まらないサフィックスは、標準ライブラリが提供するリテラル演算子のために予約されています。また、ダブルアンダースコア
__
を含むこともできません:そのようなサフィックスも同様に予約されています。
リテラル演算子がテンプレートである場合、空のパラメータリストを持たなければならず、また単一のテンプレートパラメータのみを持つことができます。そのテンプレートパラメータは、要素型が char である定数テンプレートパラメータパックでなければなりません(この場合、これは 数値リテラル演算子テンプレート として知られています):
template<char...> double operator ""_x();
|
またはクラス型の定数テンプレートパラメータ(この場合、 string literal operator template として知られる): struct A { constexpr A(const char*); }; template<A a> A operator ""_a(); |
(C++20以降) |
リテラル演算子で許可されているパラメータリストは以下のみです:
(
const
char
*
)
|
(1) | ||||||||
(
unsigned
long
long
int
)
|
(2) | ||||||||
(
long
double
)
|
(3) | ||||||||
(
char
)
|
(4) | ||||||||
(
wchar_t
)
|
(5) | ||||||||
(
char8_t
)
|
(6) | (C++20以降) | |||||||
(
char16_t
)
|
(7) | ||||||||
(
char32_t
)
|
(8) | ||||||||
(
const
char
*
,
std::size_t
)
|
(9) | ||||||||
(
const
wchar_t
*
,
std::size_t
)
|
(10) | ||||||||
(
const
char8_t
*
,
std::size_t
)
|
(11) | (C++20以降) | |||||||
(
const
char16_t
*
,
std::size_t
)
|
(12) | ||||||||
(
const
char32_t
*
,
std::size_t
)
|
(13) | ||||||||
デフォルト引数 は許可されていません。
C language linkage は許可されていません。
上記の制限を除いて、リテラル演算子とリテラル演算子テンプレートは通常の関数(および関数テンプレート)であり、インラインまたはconstexprとして宣言でき、内部リンケージまたは外部リンケージを持ち、明示的に呼び出し可能で、そのアドレスを取得できるなど。
#include <string> void operator ""_km(long double); // OK, 1.0_km で呼び出される void operator "" _km(long double); // 上記と同じ、非推奨 std::string operator ""_i18n(const char*, std::size_t); // OK template<char...> double operator ""_pi(); // OK float operator ""_e(const char*); // OK // エラー: サフィックスはアンダースコアで始まる必要がある float operator ""Z(const char*); // エラー: アンダースコアに続いて大文字で始まる名前は予約されている // (注: "" と _ の間にスペースがある) double operator"" _Z(long double); // OK。注: "" と _ の間にスペースがない double operator""_Z(long double); // OK: リテラル演算子はオーバーロード可能 double operator ""_Z(const char* args); int main() {}
注記
ユーザー定義リテラルの導入以来、固定幅整数型の フォーマットマクロ定数 を前の文字列リテラルの直後にスペースなしで使用するコードは無効となりました: std:: printf ( "%" PRId64 " \n " , INT64_MIN ) ; は以下のように置き換える必要があります std:: printf ( "%" PRId64 " \n " , INT64_MIN ) ; 。
maximal munch
のため、ユーザー定義の整数リテラルおよび浮動小数点リテラルが
p
,
P
,
(C++17以降)
e
および
E
で終わり、その後に演算子
+
または
-
が続く場合、ソースコード内で演算子とは空白または括弧で区切る必要があります:
long double operator""_E(long double); long double operator""_a(long double); int operator""_p(unsigned long long); auto x = 1.0_E+2.0; // エラー auto y = 1.0_a+2.0; // OK auto z = 1.0_E +2.0; // OK auto q = (1.0_E)+2.0; // OK auto w = 1_p+2; // エラー auto u = 1_p +2; // OK
整数または浮動小数点ユーザー定義リテラルに続くドット演算子についても同様です:
#include <chrono> using namespace std::literals; auto a = 4s.count(); // エラー auto b = 4s .count(); // OK auto c = (4s).count(); // OK
そうでなければ、単一の無効なプリプロセス数値トークン(例: 1.0 _E + 2.0 または 4s. count )が形成され、コンパイルが失敗する原因となります。
| 機能テストマクロ | 値 | 規格 | 機能 |
|---|---|---|---|
__cpp_user_defined_literals
|
200809L
|
(C++11) | User-defined literals |
キーワード
例
#include <algorithm> #include <cstddef> #include <iostream> #include <numbers> #include <string> // 度(入力パラメータ)からラジアン(戻り値)への変換に使用 constexpr long double operator""_deg_to_rad(long double deg) { long double radians = deg * std::numbers::pi_v<long double> / 180; return radians; } // カスタム型で使用 struct mytype { unsigned long long m; }; constexpr mytype operator""_mytype(unsigned long long n) { return mytype{n}; } // 副作用のために使用 void operator""_print(const char* str) { std::cout << str << '\n'; } #if __cpp_nontype_template_args < 201911 std::string operator""_x2 (const char* str, std::size_t) { return std::string{str} + str; } #else // C++20 文字列リテラル演算子テンプレート template<std::size_t N> struct DoubleString { char p[N + N - 1]{}; constexpr DoubleString(char const(&pp)[N]) { std::ranges::copy(pp, p); std::ranges::copy(pp, p + N - 1); } }; template<DoubleString A> constexpr auto operator""_x2() { return A.p; } #endif // C++20 int main() { double x_rad = 90.0_deg_to_rad; std::cout << std::fixed << x_rad << '\n'; mytype y = 123_mytype; std::cout << y.m << '\n'; 0x123ABC_print; std::cout << "abc"_x2 << '\n'; }
出力:
1.570796 123 0x123ABC abcabc
標準ライブラリ
以下のリテラル演算子は標準ライブラリで定義されています:
|
インライン名前空間で定義
std::literals::complex_literals
|
|
|
純虚数を表す
std::complex
リテラル
(関数) |
|
|
インライン名前空間で定義
std::literals::chrono_literals
|
|
|
(C++14)
|
時間を表す
std::chrono::duration
リテラル
(関数) |
|
(C++14)
|
分を表す
std::chrono::duration
リテラル
(関数) |
|
(C++14)
|
秒を表す
std::chrono::duration
リテラル
(関数) |
|
(C++14)
|
ミリ秒を表す
std::chrono::duration
リテラル
(関数) |
|
(C++14)
|
マイクロ秒を表す
std::chrono::duration
リテラル
(関数) |
|
(C++14)
|
ナノ秒を表す
std::chrono::duration
リテラル
(関数) |
|
(C++20)
|
特定の年を表す
std::chrono::year
リテラル
(関数) |
|
(C++20)
|
月の日を表す
std::chrono::day
リテラル
(関数) |
|
インライン名前空間で定義
std::literals::string_literals
|
|
|
(C++14)
|
文字配列リテラルを
basic_string
に変換
(関数) |
|
インライン名前空間で定義
std::literals::string_view_literals
|
|
|
(C++17)
|
文字配列リテラルの文字列ビューを作成
(関数) |
不具合報告
以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。
| DR | 適用対象 | 公開時の動作 | 正しい動作 |
|---|---|---|---|
| CWG 1473 | C++11 |
リテラル演算子の宣言において、
""
と
ud-suffix
の間の空白が
必須であった |
任意とした |
| CWG 1479 | C++11 | リテラル演算子がデフォルト引数を持つことができた | 禁止 |
| CWG 2521 | C++11 |
operator
""
_Bq
は、予約識別子
_Bq
を使用するため
不適格(診断不要)であった |
""
と
ud-suffix
の間に空白があるリテラル演算子構文を
非推奨とした |