Namespaces
Variants

リフレクション演算子 (C++26 以上)

ja.cppreference.net より
 
 
C++ 言語
一般的なトピック
フロー制御
条件付き実行文
if
繰り返し文 (ループ)
for
範囲for (C++11)
ジャンプ文
関数
関数宣言
ラムダ関数式
inline 指定子
動的例外仕様 (C++17 まで*)
noexcept 指定子 (C++11)
例外
名前空間
型
指定子
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
記憶域期間指定子
初期化
式
代替表現
リテラル
論理値 - 整数 - 浮動小数点
文字 - 文字列 - nullptr (C++11)
ユーザー定義 (C++11)
ユーティリティ
属性 (C++11)
型
typedef 宣言
型エイリアス宣言 (C++11)
キャスト
メモリ確保
クラス
クラス固有の関数プロパティ
explicit (C++11)
static

特殊メンバ関数
テンプレート
その他
 
 

単項 ^^ 演算子、リフレクション演算子と呼ばれ、指定された言語構成要素のリフレクションを生成します。その型は std::meta::info です。

構文

^^ :: (1)
^^ リフレクション名 (2)
^^ 型識別子 (3)
^^ 識別子式 (4)
リフレクション名 - 識別子(オプションで 修飾可能、オプションで template 曖昧解決子を使用)。この形式は 型識別子 および 識別子式
よりも優先されます。型識別子 - 型識別子
識別子式 - 識別子式

構文上、^^ のオペランドを形成できる最も長いトークン列が解析されます。結果がテンプレートを表す場合、式の直後に < が続いてはなりません。

static_assert(std::meta::is_type(^^int())); // ^^int() represents the type int()
                                            // not a function call to ^^int

template<bool> struct X {};
consteval bool operator<(std::meta::info, X<false>) { return false; }
consteval void g(std::meta::info r, X<false> xv) {
    r == ^^int && true; // error: ^^ applies to the type-id int&&
    r == ^^int & true; // error: ^^ applies to the type-id int&
    r == (^^int) && true; // OK
    r == ^^int &&&& true; // error: int &&&& is not a valid type-id
    ^^X < xv; // error: reflect-expression that represents a template is followed by <
    (^^X) < xv; // OK
    ^^X<true> < xv; // OK
}

説明

1) 式 ^^:: はグローバル名前空間を表します。
2) ^^reflection-name では、リフレクション名 が 名前探索され、以下のように表現が決定されます:
  • template 曖昧解決子 が存在する場合、結果は注入されたクラス名によって指定されたクラステンプレートを表します。
  • それ以外の場合、注入されたクラス名は型名として考慮されたときに曖昧であってはなりません(そうでなければ式は無効です)。結果はそのように指定された型を表します。
  • それ以外の場合、名前探索がオーバーロード集合を見つけた場合、そのオーバーロード集合は一意の関数テンプレートの宣言のみを含んでいなければなりません。結果はその関数テンプレートを表します。
  • それ以外の場合、名前探索が クラステンプレート、変数テンプレート、または エイリアステンプレート を見つけた場合、結果はそのテンプレートを表します。
template<typename T>
struct S {
    static constexpr std::meta::info r = ^^T;
    using type = T;
};
static_assert(S<int>::r == ^^int); // OK
static_assert(^^S<int>::type != ^^int); // OK

typedef struct X {} Y;
typedef struct Z {} Z;
constexpr std::meta::info e = ^^Y; // OK, represents the type alias Y
constexpr std::meta::info f = ^^Z; // OK, represents the type alias Z, not the type
  • それ以外の場合、名前探索が クラス型 または 列挙型 を見つけた場合、結果はその型を表します。
  • それ以外の場合、名前探索が 無名共用体 のクラスメンバを見つけた場合、結果はそのメンバを表します。
  • それ以外の場合、リフレクション名 は 識別子式 と見なされます(下記の形式 (4) を参照)。
3) 式 ^^type-id は次のように決定されるエンティティを表します:
  • 型識別子 が プレースホルダー型(例: auto)を指定する場合、式は無効です。
  • それ以外の場合、型識別子 がテンプレート引数リストを持つ エイリアステンプレート を指定する場合、結果はそのように指定された型エイリアスを表します。(その他の形式の型エイリアス名は リフレクション名 として扱われ、結果もその型エイリアスを表します。)
  • それ以外の場合、結果は 型識別子 によって示される型を表します。
4) 式 ^^id-expression は次のように決定されるエンティティを表します:
  • 識別子式 が以下を表す場合:
  • ラムダの init-capture によって宣言された変数、
  • 関数ローカルの事前定義変数 (__func__)、
  • ローカルパラメータ(requires 式によって宣言されたもの)、または
  • ローカルエンティティであり、そのエンティティが導入された地点とリフレクト式の間にラムダスコープが介在するもの(エンティティがキャプチャされているかどうかに関わらず)、
式は無効です。
  • それ以外の場合、識別子式 がオーバーロード集合を表す場合、オーバーロード解決 は一意の関数を選択しなければなりません。結果はその関数を表します。
template<typename T> void fn() requires (^^T != ^^int);
template<typename T> void fn() requires (^^T == ^^int);
template<typename T> void fn() requires (sizeof(T) == sizeof(int));
constexpr std::meta::info a = ^^fn<char>; // OK
constexpr std::meta::info b = ^^fn<int>;  // error: ambiguous

オペランドは 未評価オペランド です。

注記

リフレクション値は、std::meta::reflect_constant、std::meta::reflect_object、std::meta::reflect_function、または デフォルト初期化 された std::meta::info によっても生成できます。さらに、既存の <std::meta::info> オブジェクトに対して meta 関数を呼び出すことによってリフレクション値を得ることもできます。

型エイリアスが 型識別子 の一部として現れる場合、リフレクション演算子はその型エイリアスを保持しません。

using T = int;
static_assert(^^T != ^^int);
static_assert(^^T& == ^^int&);
static_assert(^^T const == ^^const int);

例

int arr[] = {1, 2, 3};
auto [a1, a2, a3] = arr;
[[=1]] void fn(int n);
enum Enum { A };
using Alias = int;
struct S { int mem; };
template<auto> struct TCls {};
template<auto> void TFn();
template<auto> int TVar;
template<auto N> using TAlias = TCls<N>;
template<auto> concept Concept = true;
namespace NS {}
namespace NSAlias = NS;

constexpr auto r_arr   = ^^arr; // represents a variable
constexpr auto r_sb    = ^^a3; // represents a structured binding
constexpr auto r_fn    = ^^fn; // represents a function
constexpr auto r_enum  = ^^Enum::A; // represents an enumerator
constexpr auto r_alias = ^^Alias; // represents a type alias
constexpr auto r_type  = ^^S; // represents a type
constexpr auto r_mem   = ^^S::mem; // represents a class member
constexpr auto r_tcls  = ^^TCls; // represents a class template
constexpr auto r_tfn   = ^^TFn; // represents a function template
constexpr auto r_tvar  = ^^TVar; // represents a variable template
constexpr auto r_ttype = ^^TAlias; // represents an alias template
constexpr auto r_cncpt = ^^Concept; // represents a concept
constexpr auto r_ns    = ^^NS; // represents a namespace
constexpr auto r_ns2   = ^^NSAlias; // represents a namespace alias

int main() {}

関連項目

値または テンプレートパラメータオブジェクト を表すリフレクションを返します。定数テンプレート引数として使用するのに適しています
(関数テンプレート)
オブジェクトを表すリフレクションを返します。定数テンプレート引数として使用するのに適しています
(関数テンプレート)
関数を表すリフレクションを返します。定数テンプレート引数として使用するのに適しています
(関数テンプレート)