リフレクション拡張
C++リフレクション拡張 (ISO/IEC TS 23619:2021) は、コア言語の変更を規定し、このページにリストされているC++標準ライブラリの新しいコンポーネントを定義します。
リフレクションTSはC++20標準に基づいています(ただし、コンセプトの定義はコンセプトTSのスタイルで規定されています)。
[編集] コア言語の変更
[編集] reflexpr指定子
reflexpr-specifierはreflexpr ( reflexpr-operand )の形式を取り、メタオブジェクト型(下記参照)を指定します。
reflexpr-operandは以下のいずれかです。
::
|
(1) | ||||||||
| type-id | (2) | ||||||||
| nested-name-specifier(省略可) namespace-name | (3) | ||||||||
| id-expression | (4) | ||||||||
( expression ) |
(5) | ||||||||
| function-call-expression | (6) | ||||||||
| functional-type-conv-expression | (7) | ||||||||
ここで、function-call-expressionは
postfix-expression ( expression-list(省略可) ) |
|||||||||
そして、functional-type-conv-expressionは明示的キャストを行う以下の種類の式です。
simple-type-specifier ( expression-list(省略可) ) |
(1) | ||||||||
typename-specifier ( expression-list(省略可) ) |
(2) | ||||||||
| simple-type-specifier braced-init-list | (3) | ||||||||
| typename-specifier braced-init-list | (4) | ||||||||
reflexpr-specifierのオペランドは、型、名前空間、列挙子、変数、データメンバ、関数パラメータ、キャプチャされたエンティティ、function-call-expression、functional-type-conv-expression、そして丸括弧で囲まれた式でなければなりません。reflexpr(::)はグローバル名前空間をリフレクトします。
( expression )の形式のreflexpr-operandについて、expressionは(多重に丸括弧で囲まれていてもよい)function-call-expressionまたはfunctional-type-conv-expressionでなければなりません。
丸括弧で囲まれていないオペランドがtype-idとfunctional-type-conv-expressionのどちらとしても扱える場合、それはtype-idとして扱われます。関数形式のキャストとtype-idの曖昧さを解消するために丸括弧を使用できます。例えば、デフォルトコンストラクタを持つクラス型Xが与えられた場合、reflexpr(X())は関数型X()をリフレクトし、reflexpr((X()))は式X()をリフレクトします。
オペランドがエイリアスとクラス名の両方を指す場合、reflexpr-specifierによって表される型はエイリアスをリフレクトし、reflect::Aliasを充足します。
オペランドがブロックスコープ内に宣言があり、かつその名前付きエンティティがキャプチャされてもおらず、関数パラメータでもない名前を指す場合、プログラムは不適格となります。
[編集] メタオブジェクト型
メタオブジェクト型とは、名前のない、不完全な名前空間スコープのクラス型です。ある型がメタオブジェクト型であることと、その型がコンセプトreflect::Objectを充足することは同値です。メタオブジェクト型は、reflexprのオペランドに応じて、他のコンセプトを充足することがあります。
同じオペランドにreflexprを繰り返し適用した場合に、同じ型が得られるか、異なる型が得られるかは未規定です。メタオブジェクト型が不完全なクラス型をリフレクトする場合、特定の型変換を適用することはできません。
メタオブジェクト型は、型特性や型変換を通じて、reflexprのオペランドのいくつかのプロパティを検査することを可能にします。
[編集] オーバーロード解決
function-call-expressionのpostfix-expressionがクラス型である場合、すなわちfunction-call-expression e(args)におけるeがクラス型である場合、postfix-expression(e)の型のユーザ定義変換関数は使用されません。
postfix-expressionがクラス型でない場合、それはオーバーロード解決の唯一の結果である関数を指名しなければなりません。
struct Functor { void operator()(int) const; using fptr_t = void(*)(std::nullptr_t); operator fptr_t() const; }; using Meta0 = reflexpr(Functor{}(0)); // OK // using Meta1 = reflexpr(Functor{}(nullptr)); // error: conversion function used
[編集]
エイリアスとは、typedef宣言、エイリアス宣言、またはusing宣言によって導入される名前です。
エンティティまたはエイリアスBが、エンティティまたはエイリアスAにリフレクション関連であるとは、
-
AとBが同じエンティティまたはエイリアスである、 -
Aが変数または列挙子であり、BがAの型である、 -
Aが列挙型であり、BがAの基底型である、 -
Aがクラスであり、BがAのメンバまたは基底クラスである、 -
Aが非テンプレートのエイリアスで、エンティティBを指す、 -
Aがグローバル名前空間ではなく、BがAを囲むクラスまたは名前空間である、 -
Aが丸括弧で囲まれた式 (B) である、 -
Aがクロージャ型Bのラムダキャプチャである、 -
AがラムダキャプチャBのクロージャ型である、 -
Bがfunctional-type-conv-expressionAによって指定される型である、 -
Bがfunction-call-expressionAに対してオーバーロード解決で選択された関数である、 -
Bが関数Aの戻り値の型、パラメータの型、または関数型である、または -
BがエンティティまたはエイリアスXにリフレクション関連であり、かつXがAにリフレクション関連である、
のいずれかを満たす場合を指します。リフレクション関連の関係は反射的かつ推移的ですが、対称的ではありません。
非公式に言えば、BがAにリフレクション関連であるとは、BがAの宣言または定義に関与していることを意味します。
メタオブジェクト型を生成する型変換をreflexpr-specifierによって示される型に0回以上連続して適用することで、オペランドにリフレクション関連のエンティティやエイリアスの検査が可能になります。そのようなメタオブジェクト型は、それぞれのリフレクション関連のエンティティやエイリアスをリフレクトすると言われます。
struct X; struct B { using X = ::X; typedef X Y; }; struct D : B { using B::Y; }; // ::X, but not B::X or B::Y is reflection-related to D::Y
[編集] その他
- reflexpr-operandとして使用される式は、評価されない式であり、潜在的に定数評価されます。
- デフォルトキャプチャによってラムダ式でキャプチャされる変数を決定する目的において、
reflexprオペランドは評価されないオペランドとは見なされません。 - メタオブジェクト型
Tによってリフレクトされる静的記憶域期間を持つ関数または変数は、その関数または変数を指名するid-expressionのアドレスを取るかのように、std::experimental::reflect::get_pointer<T>の特殊化によってODR-usedされます。 - メタオブジェクト型の定義は複数存在することがありますが、その型のすべての操作が同じ定数式の結果を生成する限りにおいて許されます。
- ある型がreflexpr-specifierによって示され、かつそのオペランドが
[編集] キーワード
[編集] 事前定義された機能テストマクロ
| __cpp_reflection (reflection TS) |
少なくとも201902の値は、リフレクションTSがサポートされていることを示します (マクロ定数) |
[編集] ライブラリサポート
[編集] コンセプト
| ヘッダ
<experimental/reflect> で定義 | |
| 名前空間
std::experimental::reflect で定義 | |
| インライン名前空間
std::experimental::reflect::v1 で定義 | |
| (reflection TS) |
型がメタオブジェクト型であることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型がメタオブジェクトシーケンス型であることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型がテンプレートパラメータスコープをリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型が、関連する(空の可能性もある)名前を持つエンティティまたはエイリアスをリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型が、型エイリアス、名前空間エイリアス、またはusing宣言によって導入されたエイリアスをリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型がクラスのmember-declarationをリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型が列挙子をリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型が変数またはデータメンバをリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型がRecordMember、Enumerator、またはVariableを充足するか、グローバル名前空間以外の名前空間をリフレクトすることを指定する(コンセプト) |
| (reflection TS) |
メタオブジェクト型が型を持つエンティティをリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型が名前空間をリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型がグローバル名前空間をリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型が非共用体のクラス型をリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型が列挙型をリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型がクラス型をリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型が名前空間、クラス、列挙型、関数、クロージャ型、テンプレートパラメータスコープをリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型が型をリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型が列挙子またはconstexpr変数をリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型がget_base_classesから取得された直接基底クラスをリフレクトすることを指定する(コンセプト) |
| (reflection TS) |
メタオブジェクト型が関数パラメータをリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型が関数(コンストラクタとデストラクタを含む)をリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型が式をリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型が丸括弧で囲まれた式をリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型がfunction-call-expressionをリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型がfunctional-type-conv-expressionをリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型が関数(コンストラクタとデストラクタを除く)をリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型がメンバ関数(コンストラクタとデストラクタを除く)をリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型が特殊メンバ関数をリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型がコンストラクタをリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型がデストラクタをリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型が演算子関数または変換関数をリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型が変換関数をリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型が非ジェネリックラムダのクロージャ型をリフレクトすることを指定する (コンセプト) |
| (reflection TS) |
メタオブジェクト型がラムダキャプチャをリフレクトすることを指定する (コンセプト) |
[編集] メタオブジェクト操作
| ヘッダ
<experimental/reflect> で定義 | |
| 名前空間
std::experimental::reflect で定義 | |
| インライン名前空間
std::experimental::reflect::v1 で定義 | |
| |
| (reflection TS) |
2つのメタオブジェクト型が同じエンティティまたはエイリアスをリフレクトするかどうかをチェックする (クラステンプレート) |
| (reflection TS) |
リフレクトされたエンティティまたはエイリアスの宣言の推定行番号を取得する (クラステンプレート) |
| (reflection TS) |
リフレクトされたエンティティまたはエイリアスの宣言の処理系定義の列番号を取得する (クラステンプレート) |
| (reflection TS) |
リフレクトされたエンティティまたはエイリアスの宣言の推定ファイル名を取得する (クラステンプレート) |
| |
| (reflection TS) |
メタオブジェクトシーケンスのサイズを取得する (クラステンプレート) |
| (reflection TS) |
シーケンス内の指定されたインデックスを持つメタオブジェクト型を取得する (クラステンプレート) |
| (reflection TS) |
テンプレートをメタオブジェクトシーケンスに適用する (クラステンプレート) |
| |
| (reflection TS) |
リフレクトされたエンティティまたはエイリアスが名前を持たないかどうかをチェックする (クラステンプレート) |
| (reflection TS) |
リフレクトされたエンティティまたはエイリアスの非修飾名を取得する (クラステンプレート) |
| (reflection TS) |
リフレクトされたエンティティまたはエイリアスの処理系定義の表示名を取得する (クラステンプレート) |
| |
| (reflection TS) |
リフレクトされたエイリアスに関連付けられたエンティティをリフレクトするメタオブジェクト型を取得する (クラステンプレート) |
| |
| (reflection TS) |
リフレクトされたエンティティまたはエイリアスの型をリフレクトするメタオブジェクト型を取得する (クラステンプレート) |
| (reflection TS) |
リフレクトされたエンティティまたはエイリアスの型を取得する (クラステンプレート) |
| (reflection TS) |
メタオブジェクト型が列挙型をリフレクトするかどうかをチェックする (クラステンプレート) |
| (reflection TS) |
メタオブジェクト型が共用体型をリフレクトするかどうかをチェックする (クラステンプレート) |
| (reflection TS) |
メタオブジェクト型が、それぞれclassまたはstructを使用して宣言された非共用体のクラス型をリフレクトするかどうかをチェックする (クラステンプレート) |
| |
| (reflection TS) |
リフレクトされたエンティティまたはエイリアスのスコープをリフレクトするメタオブジェクト型を取得する (クラステンプレート) |
| |
| (reflection TS) |
与えられた基底クラス関係における基底クラスをリフレクトするメタオブジェクト型を取得する (クラステンプレート) |
| |
| (reflection TS) |
リフレクトされたメンバまたは基底クラスがpublicかどうかをチェックする (クラステンプレート) |
| (reflection TS) |
リフレクトされたメンバまたは基底クラスがprotectedかどうかをチェックする (クラステンプレート) |
| (reflection TS) |
リフレクトされたメンバまたは基底クラスがprivateかどうかをチェックする (クラステンプレート) |
| |
| リフレクトされたクラスのpublicな、アクセス可能な、またはすべてのデータメンバをリフレクトする要素を持つメタオブジェクトシーケンス型を取得する (クラステンプレート) | |
| リフレクトされたクラスのpublicな、アクセス可能な、またはすべてのメンバ関数をリフレクトする要素を持つメタオブジェクトシーケンス型を取得する (クラステンプレート) | |
| (reflection TS) |
リフレクトされたクラスのすべてのコンストラクタをリフレクトする要素を持つメタオブジェクトシーケンス型を取得する (クラステンプレート) |
| (reflection TS) |
リフレクトされたクラスで宣言されたすべての演算子関数と変換関数をリフレクトする要素を持つメタオブジェクトシーケンス型を取得する (クラステンプレート) |
| (reflection TS) |
リフレクトされたクラスのデストラクタをリフレクトするメタオブジェクト型を取得する (クラステンプレート) |
| リフレクトされたクラスのpublicな、アクセス可能な、またはすべてのネストされた型またはメンバtypedefをリフレクトする要素を持つメタオブジェクトシーケンス型を取得する (クラステンプレート) | |
| リフレクトされたクラスのpublicな、アクセス可能な、またはすべての基底クラスをリフレクトする要素を持つメタオブジェクトシーケンス型を取得する (クラステンプレート) | |
| |
| (reflection TS) |
リフレクトされた列挙型がスコープ付きかどうかをチェックする (クラステンプレート) |
| (reflection TS) |
リフレクトされた列挙型の列挙子をリフレクトする要素を持つメタオブジェクトシーケンス型を取得する (クラステンプレート) |
| (reflection TS) |
リフレクトされた列挙型の基底型をリフレクトするメタオブジェクト型を取得する (クラステンプレート) |
| |
| (reflection TS) |
定数式であるリフレクトされた変数の値を取得する (クラステンプレート) |
| (reflection TS) |
変数がthread_localで宣言されているかどうかをチェックする (クラステンプレート) |
| |
| (reflection TS) |
リフレクトされたパラメータがデフォルト引数を持つかどうかをチェックする (クラステンプレート) |
| |
| (reflection TS) |
リフレクトされた関数のパラメータをリフレクトする要素を持つメタオブジェクトシーケンス型を取得する (クラステンプレート) |
| (reflection TS) |
リフレクトされた関数のパラメータリストが省略記号パラメータを含むかどうかをチェックする (クラステンプレート) |
| (reflection TS) |
リフレクトされた関数が例外をスローしないかどうかをチェックする (クラステンプレート) |
| (reflection TS) |
リフレクトされた関数がdeletedかどうかをチェックする (クラステンプレート) |
| |
| (reflection TS) |
リフレクトされた変数または関数がconstexprかどうかをチェックする (クラステンプレート) |
| |
| (reflection TS) |
リフレクトされた名前空間または関数がinlineかどうかをチェックする (クラステンプレート) |
| |
| (reflection TS) |
リフレクトされた丸括弧で囲まれた式の、丸括弧のない式をリフレクトするメタオブジェクト型を取得する (クラステンプレート) |
| |
| (reflection TS) |
リフレクトされたfunction-call-expression内の関数をリフレクトするメタオブジェクト型を取得する (クラステンプレート) |
| |
| (reflection TS) |
リフレクトされたfunctional-type-conv-expression内のコンストラクタをリフレクトするメタオブジェクト型を取得する (クラステンプレート) |
| |
| (reflection TS) |
リフレクトされた変数または関数のアドレス、またはリフレクトされた非静的メンバへのメンバポインタ値を取得する (クラステンプレート) |
| |
| リフレクトされたメンバ関数がそれぞれconst, volatile, &, または &&修飾子で宣言されているかどうかをチェックする (クラステンプレート) | |
| (reflection TS) |
リフレクトされたメンバ関数が基底クラスのメンバ関数をオーバーライドするかどうかをチェックする (クラステンプレート) |
| |
| (reflection TS) |
リフレクトされたクラスまたはメンバ関数がfinalでマークされているかどうかをチェックする (クラステンプレート) |
| |
| (reflection TS) |
リフレクトされた変数が静的記憶域期間を持つか、またはリフレクトされたメンバ関数が静的かどうかをチェックする (クラステンプレート) |
| |
| (reflection TS) |
リフレクトされた特殊メンバ関数が暗黙的に宣言されたかどうかをチェックする (クラステンプレート) |
| (reflection TS) |
リフレクトされた特殊メンバ関数が最初の宣言でdefaultedかどうかをチェックする (クラステンプレート) |
| |
| (reflection TS) |
リフレクトされたコンストラクタまたは変換関数がexplicitで宣言されているかどうかをチェックする (クラステンプレート) |
| |
| (reflection TS) |
リフレクトされたメンバ関数がvirtualかどうかをチェックする (クラステンプレート) |
| (reflection TS) |
リフレクトされたメンバ関数が純粋仮想かどうかをチェックする (クラステンプレート) |
| |
| (reflection TS) |
リフレクトされたクロージャ型のキャプチャをリフレクトする要素を持つメタオブジェクトシーケンス型を取得する (クラステンプレート) |
| (reflection TS) |
リフレクトされたクロージャ型のラムダ式のデフォルトキャプチャがそれぞれ=または&かどうかをチェックする(クラステンプレート) |
| (reflection TS) |
リフレクトされたクロージャ型のoperator()がconstで宣言されているかどうかをチェックする(クラステンプレート) |
| |
| (reflection TS) |
リフレクトされたラムダキャプチャが明示的にキャプチャされているかどうかをチェックする (クラステンプレート) |
| (reflection TS) |
リフレクトされたラムダキャプチャが初期化キャプチャかどうかをチェックする (クラステンプレート) |
[編集] ライブラリ機能テストマクロ
| ヘッダ
<experimental/reflect> で定義 | |
| __cpp_lib_reflection (reflection TS) |
少なくとも201902の値は、リフレクションTSのサポートライブラリがサポートされていることを示します (マクロ定数) |
[編集] コンセプトの充足
以下の表は、オペランドをリフレクトするメタオブジェクト型が、リフレクションTSによって導入されたコンセプトを充足するかどうかを示します。
| カテゴリ | reflexprオペランド |
充足されるコンセプト |
|---|---|---|
| 型 | 共用体を指すclass-name | reflect::Union
|
| クロージャ型を指すclass-name | reflect::Lambda
| |
| 非共用体クラスを指すclass-name | reflect::Record
| |
| enum-name | reflect::Enum
| |
| テンプレートのtype-parameter | reflect::Type, reflect::Alias | |
| decltype-specifier | reflect::Type, reflect::Alias | |
| using宣言によって導入されたtype-name | reflect::Type, reflect::Alias, reflect::ScopedMember | |
| その他のtypedef-name | reflect::Type, reflect::Alias | |
| その他のtype-id | reflect::Type
| |
| Namespace | namespace-alias | reflect::Namespace, reflect::Alias |
| グローバル名前空間 | reflect::GlobalScope
| |
| その他の名前空間 | reflect::Namespace
| |
| Expression | データメンバの名前 | reflect::Variable
|
| 変数の名前 | reflect::Variable
| |
| 列挙子の名前 | reflect::Enumerator
| |
| 関数パラメータの名前 | reflect::FunctionParameter
| |
| キャプチャされたエンティティの名前 | reflect::LambdaCapture
| |
| 丸括弧で囲まれた式 | reflect::ParenthesizedExpression
| |
| function-call-expression | reflect::FunctionCallExpression
| |
| functional-type-conv-expression | reflect::FunctionalTypeConversion
|
id-expression形式のオペランドが定数式である場合、reflexpr-specifierによって指定される型はreflect::Constantも充足します。
reflexpr-operandがクラスメンバを指す場合、reflexpr-specifierによって表される型はreflect::RecordMemberも充足します。
[編集] 関連項目
| ある型の情報を保持し、typeid演算子によって返されるクラス (クラス) | |
| (C++11) |
コンパイル時型情報ユーティリティ |