命名空间
变体
操作

反射扩展

来自 cppreference.cn
< cpp‎ | 实验性
 
 
实验性
技术规范
文件系统库 (文件系统 TS)
库基础 (库基础 TS)
库基础 2 (库基础 TS v2)
库基础 3 (库基础 TS v3)
并行性扩展 (并行性 TS)
并行性扩展 2 (并行性 TS v2)
并发性扩展 (并发性 TS)
并发扩展 2 (并发 TS v2)
概念 (概念 TS)
范围 (范围 TS)
反射 (反射 TS)
数学特殊函数 (特殊函数 TR)
实验性非 TS
模式匹配
线性代数
std::execution
契约
2D 图形
 
反射扩展
概念
元对象操作
Variable
FunctionParameter
Callable
VariableCallable
NamespaceCallable
ParenthesizedExpression
FunctionCallExpression
FunctionalConversion
VariableFunction
 

C++ 反射扩展,ISO/IEC TS 23619:2021,指定了对核心语言的修改,并定义了本页列出的 C++ 标准库新组件。

反射 TS 基于 C++20 标准(但概念的定义是按照概念 TS的风格指定的)。

目录

[编辑] 核心语言变更

[编辑] reflexpr-说明符

一个 reflexpr-说明符 的形式为 reflexpr ( reflexpr-操作数 ),并指定一个元对象类型(见下文)。

reflexpr-操作数 可以是以下之一:

:: (1)
类型标识 (2)
嵌套名说明符(可选) 命名空间名 (3)
id-表达式 (4)
( 表达式 ) (5)
函数调用表达式 (6)
函数式类型转换表达式 (7)

其中 函数调用表达式

后缀表达式 ( 表达式列表(可选) )

函数式类型转换表达式 是以下执行显式转换的表达式类型

简单类型说明符 ( 表达式列表(可选) ) (1)
typename-说明符 ( 表达式列表(可选) ) (2)
简单类型说明符 大括号初始化列表 (3)
typename-说明符 大括号初始化列表 (4)

reflexpr-说明符 的操作数应为类型命名空间枚举器、变量、数据成员函数参数捕获实体函数调用表达式函数式类型转换表达式,以及带括号的表达式。reflexpr(::) 反射全局命名空间。

对于形式为 ( 表达式 )reflexpr-操作数,该 表达式 应为(可能多层括号的)函数调用表达式函数式类型转换表达式

如果一个无括号操作数可以被视为 类型标识函数式类型转换表达式,则它被视为 类型标识。括号可用于区分函数式类型转换和 类型标识。例如,给定一个具有默认构造函数的类类型 Xreflexpr(X()) 反射函数类型 X(),而 reflexpr((X())) 反射表达式 X()

如果操作数同时指定一个别名和一个类名,则由 reflexpr-说明符表示的类型将反射该别名并满足 `reflect::Alias`。

如果操作数指定一个在块作用域中声明的名称,并且该命名实体既未被捕获也不是函数参数,则程序格式错误。

[编辑] 元对象类型

元对象类型是一种未命名、不完整的命名空间作用域类类型。当且仅当一个类型是元对象类型时,它才满足 `reflect::Object` 概念。元对象类型可能满足其他概念,具体取决于 `reflexpr` 的操作数。

反复将 `reflexpr` 应用于同一操作数是否产生相同或不同的类型是未指定的。如果元对象类型反映一个不完整的类类型,则某些类型转换无法应用。

元对象类型允许通过类型特征或类型转换检查 `reflexpr` 操作数的一些属性。

[编辑] 重载决议

如果 函数调用表达式后缀表达式 是类类型,即 e函数调用表达式 e(args) 中是类类型,则不应使用 后缀表达式 (e) 类型的用户定义转换函数

如果 后缀表达式 不是类类型,它应命名一个函数,该函数是重载决议的唯一结果。

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 反射相关,如果

  1. AB 是相同的实体或别名,
  2. A 是变量或枚举器,且 BA 的类型,
  3. A 是枚举,且 BA 的基础类型,
  4. A 是类,且 BA 的成员或基类,
  5. A 是指定实体 B 的非模板别名,
  6. A 不是全局命名空间,且 BA 的封闭类或命名空间,
  7. A 是带括号的表达式 ( B ),
  8. A 是闭包类型 B 的 lambda 捕获,
  9. A 是 lambda 捕获 B 的闭包类型,
  10. B 是由 函数式类型转换表达式 A 指定的类型,
  11. B 是通过重载决议为 函数调用表达式 A 选择的函数,
  12. B 是函数 A 的返回类型、参数类型或函数类型,或者
  13. B 与实体或别名 X 反射相关,且 XA 反射相关。

反射关系是自反和传递的,但不是对称的。

非正式地说,BA 反射相关的情况意味着 B 参与了 A 的声明或定义。

对由 reflexpr-说明符 表示的类型进行零次或多次连续的类型转换(产生元对象类型),可以检查与操作数反射相关的实体和别名;这样的元对象类型被认为反映了相应的反射相关实体或别名。

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-操作数 的表达式是未求值表达式,并且可能在编译时求值
  • 为了确定通过捕获默认值在 lambda 表达式中捕获的变量,`reflexpr` 操作数不被视为未求值操作数。
  • 由元对象类型 `T` 反射的具有静态存储期的函数或变量,通过特化 std::experimental::reflect::get_pointer<T> 进行odr-use,如同通过获取提名该函数或变量的 id-expression 的地址一样。
  • 可以有多个元对象类型的定义,只要所有对该类型的操作都产生相同的常量表达式结果。
  • 如果一个类型是由 reflexpr-说明符表示的,并且其操作数,则该类型是依赖的

[编辑] 关键字

reflexpr

[编辑] 预定义特性测试宏

__cpp_reflection
(反射 TS)
值至少为 201902 表示支持反射 TS
(宏常量)

[编辑] 库支持

[编辑] 概念

定义于头文件 <experimental/reflect>
定义于命名空间 std::experimental::reflect
定义于内联命名空间 std::experimental::reflect::v1
(反射 TS)
指定一个类型是元对象类型
(概念)
(反射 TS)
指定一个元对象类型是元对象序列类型
(概念)
指定元对象类型反映一个模板参数作用域
(概念)
(反射 TS)
指定一个元对象类型反映一个具有关联(可能为空)名称的实体或别名
(概念)
(反射 TS)
指定元对象类型反映类型别名、命名空间别名或通过 using-声明引入的别名
(概念)
(反射 TS)
指定元对象类型反映类的一个 成员声明
(概念)
(反射 TS)
指定元对象类型反映枚举器
(概念)
(反射 TS)
指定元对象类型反映变量或数据成员
(概念)
(反射 TS)
指定一个元对象类型满足 `RecordMember`、`Enumerator` 或 `Variable`,或者反映全局命名空间以外的命名空间
(概念)
(反射 TS)
指定元对象类型反映一个具有类型的实体
(概念)
(反射 TS)
指定一个元对象类型反映一个命名空间
(概念)
(反射 TS)
指定一个元对象类型反映全局命名空间
(概念)
(反射 TS)
指定元对象类型反映非联合类类型
(概念)
(反射 TS)
指定元对象类型反映枚举类型
(概念)
(反射 TS)
指定元对象类型反映类类型
(概念)
(反射 TS)
指定一个元对象类型反映一个命名空间、类、枚举、函数、闭包类型、模板参数作用域
(概念)
(反射 TS)
指定一个元对象类型反映一个类型
(概念)
(反射 TS)
指定一个元对象类型反映一个枚举器或一个 constexpr 变量
(概念)
(反射 TS)
指定元对象类型反映从 `get_base_classes` 获取的直接基类
(概念)
指定一个元对象类型反映一个函数参数
(概念)
(反射 TS)
指定元对象类型反映一个函数(包括构造函数和析构函数)
(概念)
(反射 TS)
指定一个元对象类型反映一个表达式
(概念)
指定一个元对象类型反映一个带括号的表达式
(概念)
指定元对象类型反映一个 函数调用表达式
(概念)
指定一个元对象类型反映一个 函数式类型转换表达式
(概念)
(反射 TS)
指定一个元对象类型反映一个函数(不包括构造函数和析构函数)
(概念)
(反射 TS)
指定元对象类型反映一个成员函数(不包括构造函数和析构函数)
(概念)
指定一个元对象类型反映一个特殊成员函数
(概念)
(反射 TS)
指定一个元对象类型反映一个构造函数
(概念)
(反射 TS)
指定一个元对象类型反映一个析构函数
(概念)
(反射 TS)
指定一个元对象类型反映一个运算符函数或一个转换函数
(概念)
指定一个元对象类型反映一个转换函数
(概念)
(反射 TS)
指定元对象类型反映非泛型 lambda 的闭包类型
(概念)
(反射 TS)
指定一个元对象类型反映一个 lambda 捕获
(概念)

[编辑] 元对象操作

定义于头文件 <experimental/reflect>
定义于命名空间 std::experimental::reflect
定义于内联命名空间 std::experimental::reflect::v1
Object 操作
(反射 TS)
检查两个元对象类型是否反映相同的实体或别名
(类模板)
(反射 TS)
获取被反射实体或别名声明的推定行号
(类模板)
获取被反射实体或别名声明的实现定义的列号
(类模板)
获取被反射实体或别名声明的推定文件名
(类模板)
ObjectSequence 操作
(反射 TS)
获取元对象序列的大小
(类模板)
(反射 TS)
获取序列中指定索引的元对象类型
(类模板)
(反射 TS)
将模板应用于元对象序列
(类模板)
Named 操作
(反射 TS)
检查被反射实体或别名是否未命名
(类模板)
(反射 TS)
获取被反射实体或别名的非限定名称
(类模板)
获取被反射实体或别名的实现定义的显示名称
(类模板)
Alias 操作
(反射 TS)
获取反映被反射别名的关联实体的元对象类型
(类模板)
Type 操作
(反射 TS)
获取反映被反射实体或别名类型的元对象类型
(类模板)
获取被反射实体或别名的类型
(类模板)
(反射 TS)
检查元对象类型是否反映枚举类型
(类模板)
(反射 TS)
检查元对象类型是否反映联合类型
(类模板)
检查元对象类型是否反映使用 classstruct 分别声明的非联合类类型
(类模板)
ScopeMember 操作
(反射 TS)
获取反映被反射实体或别名作用域的元对象类型
(类模板)
Base 操作
(反射 TS)
获取反映给定基类关系中基类的元对象类型
(类模板)
RecordMemberBase 操作
(反射 TS)
检查被反射成员或基类是否为公共的
(类模板)
(反射 TS)
检查被反射成员或基类是否受保护
(类模板)
(反射 TS)
检查被反射成员或基类是否为私有的
(类模板)
Record 操作
获取一个元对象序列类型,其元素反映被反射类的公共、可访问或所有数据成员
(类模板)
获取一个元对象序列类型,其元素反映被反射类的公共、可访问或所有成员函数
(类模板)
获取一个元对象序列类型,其元素反映被反射类的所有构造函数
(类模板)
(反射 TS)
获取一个元对象序列类型,其元素反映在被反射类中声明的所有运算符函数和转换函数
(类模板)
(反射 TS)
获取反映被反射类析构函数的元对象类型
(类模板)
获取一个元对象序列类型,其元素反映被反射类的公共、可访问或所有嵌套类型或成员 typedef
(类模板)
获取一个元对象序列类型,其元素反映被反射类的公共、可访问或所有基类
(类模板)
Enum 操作
(反射 TS)
检查被反射枚举是否为作用域枚举
(类模板)
(反射 TS)
获取一个元对象序列类型,其元素反映被反射枚举的枚举器
(类模板)
获取反映被反射枚举基础类型的元对象类型
(类模板)
Variable 操作
(反射 TS)
获取被反射变量的值,该值是一个常量表达式
(类模板)
(反射 TS)
检查变量是否使用 thread_local 声明
(类模板)
FunctionParameter 操作
检查被反射参数是否具有默认参数
(类模板)
Callable 操作
(反射 TS)
获取一个元对象序列类型,其元素反映被反射函数的参数
(类模板)
(反射 TS)
检查被反射函数的参数列表是否包含省略号参数
(类模板)
(反射 TS)
检查被反射函数是否不抛出异常
(类模板)
(反射 TS)
检查被反射函数是否已删除
(类模板)
VariableCallable 操作
(反射 TS)
检查被反射变量或函数是否为 constexpr
(类模板)
NamespaceCallable 操作
(反射 TS)
检查被反射命名空间或函数是否为 inline
(类模板)
ParenthesizedExpression 操作
获取反映被反射带括号表达式的无括号表达式的元对象类型
(类模板)
FunctionCallExpression 操作
(反射 TS)
获取反映被反射 函数调用表达式 中函数的元对象类型
(类模板)
FunctionalTypeConversion 操作
(反射 TS)
获取反映被反射 函数式类型转换表达式 中构造函数的元对象类型
(类模板)
VariableFunction 操作
(反射 TS)
获取被反射变量或函数的地址,或指向被反射非静态成员的成员指针值
(类模板)
MemberFunction 操作
分别检查被反射成员函数是否声明了 constvolatile&&& 限定符
(类模板)
(反射 TS)
检查被反射成员函数是否覆盖基类的成员函数
(类模板)
RecordMemberFunction 操作
(反射 TS)
检查被反射类或成员函数是否用 final 标记
(类模板)
VariableMemberFunction 操作
(反射 TS)
检查被反射变量是否为静态存储期,或者被反射成员函数是否为静态的
(类模板)
SpecialMemberFunction 操作
检查被反射的特殊成员函数是否是隐式声明的
(类模板)
(反射 TS)
检查被反射的特殊成员函数在其第一次声明时是否已默认
(类模板)
ConstructorConversionOperator 操作
(反射 TS)
检查被反射的构造函数或转换函数是否用 explicit 声明
(类模板)
MemberFunctionDestructor 操作
(反射 TS)
检查被反射的成员函数是否为虚函数
(类模板)
(反射 TS)
检查被反射的成员函数是否为纯虚函数
(类模板)
Lambda 操作
(反射 TS)
获取一个元对象序列类型,其元素反映被反射闭包类型的捕获
(类模板)
检查被反射闭包类型的 lambda 表达式的捕获默认值是 = 还是 &
(类模板)
检查被反射闭包类型的 operator() 是否用 const 声明
(类模板)
LambdaCapture 操作
检查被反射的 lambda 捕获是否显式捕获
(类模板)
(反射 TS)
检查被反射的 lambda 捕获是否是初始化捕获
(类模板)

[编辑] 库特性测试宏

定义于头文件 <experimental/reflect>
__cpp_lib_reflection
(反射 TS)
值至少为 201902 表示支持反射 TS 的支持库
(宏常量)

[编辑] 概念的满足

下表列出了反映操作数的元对象类型是否满足反射 TS 引入的概念。

分类 reflexpr 操作数 满足的概念
类型 指定 联合体类名 reflect::Union
指定 闭包类型类名 reflect::Lambda
指定非联合类的 类名 reflect::Record
枚举名 reflect::Enum
模板 类型参数 reflect::Type, reflect::Alias
decltype-说明符 reflect::Type, reflect::Alias
通过 using-声明 引入的 类型名 reflect::Type, reflect::Alias, reflect::ScopedMember
任何其他 typedef-名 reflect::Type, reflect::Alias
任何其他 类型标识 reflect::Type
Namespace 命名空间别名 reflect::Namespace, reflect::Alias
全局命名空间 reflect::GlobalScope
任何其他命名空间 reflect::Namespace
Expression 数据成员的名称 reflect::Variable
变量的名称 reflect::Variable
枚举器的名称 reflect::Enumerator
函数参数的名称 reflect::FunctionParameter
捕获实体的名称 reflect::LambdaCapture
带括号的表达式 reflect::ParenthesizedExpression
函数调用表达式 reflect::FunctionCallExpression
函数式类型转换表达式 reflect::FunctionalTypeConversion

如果 id-expression 形式的操作数是常量表达式,则由 reflexpr-说明符指定的类型也满足 `reflect::Constant`。

如果 reflexpr-操作数指定类成员,则由 reflexpr-说明符表示的类型也满足 `reflect::RecordMember`。

[编辑] 另请参阅

包含某些类型信息的类,由 typeid 运算符返回
(类) [编辑]
编译时类型信息工具[编辑]