Namespaces
Variants

反射操作符 (C++26起)

来自 zh.cppreference.net
 
 
C++ 语言
主题
流程控制
条件执行语句
if
迭代语句(循环)
for
range-for (C++11)
跳转语句
函数
函数声明
Lambda 函数表达式
inline 说明符
动态异常规格说明 (直到 C++17*)
noexcept 说明符 (C++11)
异常
命名空间
类型
说明符
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
存储期说明符
初始化
 
 

一元 ^^运算符,称为 反射运算符,返回给定语言构造的反射,其类型为 std::meta::info。

语法

^^ :: (1)
^^ reflection-name (2)
^^ type-id (3)
^^ id-expression (4)
reflection-name - 一个标识符,可选地 受限,可选使用 template 消歧义符。此形式优先于 type-id 和 id-expression
type-id - 一个 type-id
id-expression - 一个 id-expression

可以语法上构成操作数的最长标记序列 ^^被解析。如果结果表示一个模板,则该表达式不能直接后跟 <。

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中,reflection-name 被 查找,并根据如下规则确定表示:
  • 如果 template 消歧义符存在,则结果代表由注入类命名的类模板。
  • 否则,注入类名作为类型名时必须无歧义(否则表达式无效)。结果代表如此命名的类型。
  • 否则,如果查找找到一个重载集,该重载集必须只包含唯一函数模板的声明。结果代表该函数模板。
  • 否则,如果查找找到一个 类模板、变量模板或 别名模板,则结果代表该模板。
  • 否则,如果查找找到一个类型 模板形参,则结果代表对应实参的类型。
  • 否则,如果查找找到一个 typedef 名称或 类型别名,则结果代表该类型别名。
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
  • 否则,如果查找找到一个 类类型或一个 枚举类型,则结果代表该类型。
  • 否则,如果查找找到一个 匿名联合体的类成员,则结果代表该成员。
  • 否则,reflection-name 被视为一个 id-expression(见形式 (4)下文)。
3) 表达式 ^^type-id代表一个由如下方式确定的实体:
  • 如果 type-id指定一个 占位符类型(例如 auto),则表达式无效。
  • 否则,如果 type-id 指定一个 别名模板带有模板实参列表,则结果代表如此命名的类型别名。(其他形式的类型别名名称将被视为 reflection-name,结果也将代表该类型别名。)
  • 否则,结果代表 type-id所指代的类型。
4) 表达式 ^^id-expression代表一个由如下方式确定的实体:
  • 如果 id-expression 代表:
  • 由 lambda 的 初始化捕获声明的变量,
  • 一个 函数局部预定义变量(__func__),
  • 一个 局部形参由 requires表达式声明,或
  • 一个局部实体,其引入点和反射表达式之间有 lambda 作用域介入(无论该实体是否被捕获),
则该表达式无效。
  • 否则,如果 id-expression 代表一个重载集,重载决议必须选择一个唯一函数。结果代表该函数。
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产生。此外,可以通过调用 <meta>函数并传入已有的 std::meta::info对象来获得反射值。

如果类型别名作为 type-id的一部分出现,则反射操作符不会保留该类型别名。

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() {}

参阅

返回表示一个值或 模板形参对象的反射,适合用作常量模板实参
(函数模板)
返回表示一个对象的反射,适合用作常量模板实参
(函数模板)
返回表示一个函数的反射,适合用作常量模板实参
(函数模板)