reflection 的扩展
C++ Reflection 扩展,ISO/IEC TS 23619:2021,指定了对核心语言的修改,并为本页列出的 C++ 标准库定义了新的组件。
Reflection TS 基于 C++20 标准(除了概念的定义是以 Concepts TS 的风格指定的)。
[编辑] 核心语言更改 (Core language changes)
[编辑] reflexpr-说明符 (reflexpr-specifier)
reflexpr-说明符 (reflexpr-specifier) 的形式为 reflexpr
(
reflexpr-运算数 (reflexpr-operand) )
,并指定一个元对象类型(见下文)。
reflexpr-运算数 (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) 是以下执行 显式转型 (explict cast) 的表达式种类
简单类型说明符 (simple-type-specifier) ( 表达式列表 (expression-list)(可选) ) |
(1) | ||||||||
typename-说明符 (typename-specifier) ( 表达式列表 (expression-list)(可选) ) |
(2) | ||||||||
简单类型说明符 (simple-type-specifier) 花括号初始化列表 (braced-init-list) | (3) | ||||||||
typename-说明符 (typename-specifier) 花括号初始化列表 (braced-init-list) | (4) | ||||||||
reflexpr-说明符 (reflexpr-specifier) 的运算数应为 类型 (type)、命名空间 (namespace)、枚举器 (enumerator)、变量 (variable)、数据成员 (data member)、函数形参 (function parameter)、捕获实体 (captured entity)、函数调用表达式 (function-call-expression) 或 函数式类型转换表达式 (functional-type-conv-expression) 以及带括号的表达式。reflexpr(::) 反射全局命名空间。
对于 (
表达式 (expression) )
形式的 reflexpr-运算数 (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-说明符 (reflexpr-specifier) 表示的类型将反射别名并满足 reflect::Alias
。
如果运算数指定了一个名称,其声明包含在块作用域中,并且命名实体既未捕获也不是函数形参,则程序是非良构的。
[编辑] 元对象类型 (Meta-object types)
元对象类型 (meta-object type) 是一种未命名的、不完整的命名空间作用域类类型。当且仅当类型是元对象类型时,类型才满足概念 reflect::Object
。元对象类型可能满足其他概念,具体取决于 reflexpr
的运算数。
重复将 reflexpr
应用于同一运算数是否产生相同类型或不同类型是未指定的。如果元对象类型反射一个不完整的类类型,则某些类型转换无法应用。
元对象类型允许通过对其进行类型特征或类型转换来检查 reflexpr
运算数的某些属性。
[编辑] 重载决议 (Overload resolution)
如果 函数调用表达式 (function-call-expression) 的 后缀表达式 (postfix-expression) 是类类型,即 e 在 函数调用表达式 (function-call-expression) e(args) 中是类类型,则不得使用 后缀表达式 (postfix-expression) (e) 类型的 用户定义的转换函数 (user-defined conversion function)。
如果 后缀表达式 (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
[编辑]
别名 (alias) 是由 typedef 声明、别名声明 (alias-declaration) 或 using-声明 (using-declaration) 引入的名称。
实体或别名 B
与 reflection 相关 (reflection-related) 于实体或别名 A
,如果
-
A
和B
是相同的实体或别名, -
A
是变量或枚举器,B
是A
的类型, -
A
是枚举,B
是A
的底层类型, -
A
是类,B
是A
的成员或基类, -
A
是指定实体B
的非模板别名, -
A
不是全局命名空间,B
是A
的封闭类或命名空间, -
A
是带括号的表达式 (B
), -
A
是闭包类型B
的 lambda 捕获, -
A
是 lambda 捕获B
的闭包类型, -
B
是由 函数式类型转换表达式 (functional-type-conv-expression)A
指定的类型, -
B
是重载决议为 函数调用表达式 (function-call-expression)A
选择的函数, -
B
是函数A
的返回类型、形参类型或函数类型,或 -
B
与实体或别名X
reflection 相关,并且X
与A
reflection 相关。
Reflection-relation 关系是自反的和传递的,但不是对称的。
通俗地说,B
与 A
reflection 相关的情况意味着 B
参与了 A
的声明或定义。
对 reflexpr-说明符 (reflexpr-specifier) 表示的类型零次或多次连续应用产生元对象类型的类型转换,可以检查与运算数 reflection 相关的实体和别名;这样的元对象类型被称为反射各自的 reflection 相关实体或别名。
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
[编辑] 杂项 (Miscellaneous)
- 用作 reflexpr-运算数 (reflexpr-operand) 的表达式是 未求值表达式 (unevaluated expressions) 和 潜在常量求值 (potentially constant evaluated)。
- 为了确定 lambda 表达式中通过捕获默认值捕获的变量 (captured in a lambda expression),
reflexpr
运算数不被视为未求值的运算数。 - 静态 存储期 (storage duration) 的函数或变量,由元对象类型
T
反射,被特化 std::experimental::reflect::get_pointer<T> odr-使用 (odr-used),就像通过获取提名函数或变量的标识表达式的地址一样。 - 元对象类型可以有多个定义,只要对此类型的所有操作都产生相同的常量表达式结果即可。
- 如果类型由 reflexpr-说明符 (reflexpr-specifier) 表示,并且运算数
- 是 类型依赖表达式 (type-dependent expression) 或(可能带括号的)函数式类型转换表达式 (functional-type-conv-expression),其中至少有一个类型依赖的直接子表达式,或者
- 指定依赖类型或 未知特化 (unknown specialization) 的成员或 值依赖常量表达式 (value-dependent constant expression),则该类型是 依赖的 (dependent)。
[编辑] 关键字 (Keywords)
[编辑] 预定义的特性测试宏 (Predefined feature testing macros)
__cpp_reflection (reflection TS) |
至少为 201902 的值表示支持 Reflection TS (宏常量 (macro constant)) |
[编辑] 库支持 (Library support)
[编辑] 概念 (Concepts)
定义于头文件
<experimental/reflect> | |
定义于命名空间
std::experimental::reflect | |
定义于内联命名空间
std::experimental::reflect::v1 | |
(reflection TS) |
指定类型为元对象类型 (概念 (concept)) |
(reflection TS) |
指定元对象类型为元对象序列类型 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射模板形参作用域 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射具有关联名称(可能为空)的实体或别名 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射类型别名、命名空间别名或由 using-声明 引入的别名 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射类的 成员声明 (member-declaration) (概念 (concept)) |
(reflection TS) |
指定元对象类型反射枚举器 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射变量或数据成员 (概念 (concept)) |
(reflection TS) |
指定元对象类型满足 RecordMember 、Enumerator 或 Variable ,或反射全局命名空间以外的命名空间(概念 (concept)) |
(reflection TS) |
指定元对象类型反射具有类型的实体 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射命名空间 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射全局命名空间 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射非联合类类型 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射枚举类型 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射类类型 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射命名空间、类、枚举、函数、闭包类型、模板形参作用域 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射类型 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射枚举器或 constexpr 变量 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射从 get_base_classes 获取的直接基类(概念 (concept)) |
(reflection TS) |
指定元对象类型反射函数形参 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射函数(包括构造函数和析构函数) (概念 (concept)) |
(reflection TS) |
指定元对象类型反射表达式 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射带括号的表达式 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射 函数调用表达式 (function-call-expression) (概念 (concept)) |
(reflection TS) |
指定元对象类型反射 函数式类型转换表达式 (functional-type-conv-expression) (概念 (concept)) |
(reflection TS) |
指定元对象类型反射函数(不包括构造函数和析构函数) (概念 (concept)) |
(reflection TS) |
指定元对象类型反射成员函数(不包括构造函数和析构函数) (概念 (concept)) |
(reflection TS) |
指定元对象类型反射特殊成员函数 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射构造函数 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射析构函数 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射运算符函数或转换函数 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射转换函数 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射非泛型 lambda 的闭包类型 (概念 (concept)) |
(reflection TS) |
指定元对象类型反射 lambda 捕获 (概念 (concept)) |
[编辑] 元对象操作 (Meta-object operations)
定义于头文件
<experimental/reflect> | |
定义于命名空间
std::experimental::reflect | |
定义于内联命名空间
std::experimental::reflect::v1 | |
| |
(reflection TS) |
检查两个元对象类型是否反射相同的实体或别名 (类模板 (class template)) |
(reflection TS) |
获取反射实体或别名的声明的假定行号 (类模板 (class template)) |
(reflection TS) |
获取反射实体或别名的声明的实现定义的列号 (类模板 (class template)) |
(reflection TS) |
获取反射实体或别名的声明的假定文件名 (类模板 (class template)) |
| |
(reflection TS) |
获取元对象序列的大小 (类模板 (class template)) |
(reflection TS) |
获取序列中具有指定索引的元对象类型 (类模板 (class template)) |
(reflection TS) |
将模板应用于元对象序列 (类模板 (class template)) |
| |
(reflection TS) |
检查反射实体或别名是否未命名 (类模板 (class template)) |
(reflection TS) |
获取反射实体或别名的非限定名称 (类模板 (class template)) |
(reflection TS) |
获取反射实体或别名的实现定义的显示名称 (类模板 (class template)) |
| |
(reflection TS) |
获取反射别名的关联实体的元对象类型 (类模板 (class template)) |
| |
(reflection TS) |
获取反射实体或别名的类型的元对象类型 (类模板 (class template)) |
(reflection TS) |
获取反射实体或别名的类型 (类模板 (class template)) |
(reflection TS) |
检查元对象类型是否反射枚举类型 (类模板 (class template)) |
(reflection TS) |
检查元对象类型是否反射联合类型 (类模板 (class template)) |
(reflection TS) |
检查元对象类型是否反射非联合类类型,其声明分别使用 class 或 struct (类模板 (class template)) |
| |
(reflection TS) |
获取反射实体或别名的作用域的元对象类型 (类模板 (class template)) |
| |
(reflection TS) |
获取反射给定基类关系中基类的元对象类型 (类模板 (class template)) |
| |
(reflection TS) |
检查反射成员或基类是否为 public (类模板 (class template)) |
(reflection TS) |
检查反射成员或基类是否为 protected (类模板 (class template)) |
(reflection TS) |
检查反射成员或基类是否为 private (类模板 (class template)) |
| |
获取元对象序列类型,其元素反射反射类的 public、可访问或所有数据成员 (类模板 (class template)) | |
获取元对象序列类型,其元素反射反射类的 public、可访问或所有成员函数 (类模板 (class template)) | |
(reflection TS) |
获取元对象序列类型,其元素反射反射类的所有构造函数 (类模板 (class template)) |
(reflection TS) |
获取元对象序列类型,其元素反射反射类中声明的所有运算符函数和转换函数 (类模板 (class template)) |
(reflection TS) |
获取反射类的析构函数的元对象类型 (类模板 (class template)) |
获取元对象序列类型,其元素反射反射类的 public、可访问或所有嵌套类型或成员 typedef (类模板 (class template)) | |
获取元对象序列类型,其元素反射反射类的 public、可访问或所有基类 (类模板 (class template)) | |
| |
(reflection TS) |
检查反射枚举是否为作用域枚举 (类模板 (class template)) |
(reflection TS) |
获取元对象序列类型,其元素反射反射枚举的枚举器 (类模板 (class template)) |
(reflection TS) |
获取反射枚举的底层类型的元对象类型 (类模板 (class template)) |
| |
(reflection TS) |
获取反射变量的值,该值是常量表达式 (类模板 (class template)) |
(reflection TS) |
检查变量是否使用 thread_local 声明 (类模板 (class template)) |
| |
(reflection TS) |
检查反射形参是否具有默认实参 (类模板 (class template)) |
| |
(reflection TS) |
获取元对象序列类型,其元素反射反射函数的形参 (类模板 (class template)) |
(reflection TS) |
检查反射函数的形参列表是否包含省略号形参 (类模板 (class template)) |
(reflection TS) |
检查反射函数是否为非抛出 (non-throwing) (类模板 (class template)) |
(reflection TS) |
检查反射函数是否已删除 (类模板 (class template)) |
| |
(reflection TS) |
检查反射变量或函数是否为 constexpr (类模板 (class template)) |
| |
(reflection TS) |
检查反射命名空间或函数是否为 inline (类模板 (class template)) |
| |
(reflection TS) |
获取反射带括号的表达式的未带括号的表达式的元对象类型 (类模板 (class template)) |
| |
(reflection TS) |
获取反射 函数调用表达式 (function-call-expression) 中函数的元对象类型 (类模板 (class template)) |
| |
(reflection TS) |
获取反射 函数式类型转换表达式 (functional-type-conv-expression) 中构造函数的元对象类型 (类模板 (class template)) |
| |
(reflection TS) |
获取反射变量或函数的地址,或反射非静态成员的成员指针值 (类模板 (class template)) |
| |
检查反射成员函数是否分别使用 const、volatile、& 或 && 限定符声明 (类模板 (class template)) | |
(reflection TS) |
检查反射成员函数是否覆盖基类的成员函数 (类模板 (class template)) |
| |
(reflection TS) |
检查反射类或成员函数是否标记为 final (类模板 (class template)) |
| |
(reflection TS) |
检查反射变量是否为静态存储期,或者反射成员函数是否为静态 (类模板 (class template)) |
| |
(reflection TS) |
检查反射特殊成员函数是否为隐式声明 (类模板 (class template)) |
(reflection TS) |
检查反射特殊成员函数是否在其首次声明中被预置 (defaulted) (类模板 (class template)) |
| |
(reflection TS) |
检查反射构造函数或转换函数是否使用 explicit 声明 (类模板 (class template)) |
| |
(reflection TS) |
检查反射的成员函数是否为虚函数 (类模板 (class template)) |
(reflection TS) |
检查反射的成员函数是否为纯虚函数 (类模板 (class template)) |
| |
(reflection TS) |
获取元对象序列类型,其元素反映了反射的闭包类型的捕获 (类模板 (class template)) |
(reflection TS) |
检查反射的闭包类型的 lambda 表达式的捕获默认值是否分别为 = 或 & (类模板 (class template)) |
(reflection TS) |
检查反射的闭包类型的 operator() 是否使用 const 声明(类模板 (class template)) |
| |
(reflection TS) |
检查反射的 lambda 捕获是否为显式捕获 (类模板 (class template)) |
(reflection TS) |
检查反射的 lambda 捕获是否为初始化捕获 (类模板 (class template)) |
[编辑] 库功能测试宏
定义于头文件
<experimental/reflect> | |
__cpp_lib_reflection (reflection TS) |
至少为 201902 的值表示支持 Reflection TS 的支持库 (宏常量 (macro constant)) |
[编辑] 概念的满足
下表列出了反映操作数的元对象类型是否满足 Reflection TS 引入的概念。
类别 | reflexpr 操作数 |
满足的概念 |
---|---|---|
类型 (Type) | class-name 指定 联合体 | reflect::Union
|
class-name 指定 闭包类型 | reflect::Lambda
| |
class-name 指定非联合体的类 | reflect::Record
| |
enum-name | reflect::Enum
| |
template type-parameter | reflect::Type , reflect::Alias | |
decltype-specifier | reflect::Type , reflect::Alias | |
type-name 由 using-声明 引入 | 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) |
编译时类型信息实用工具 |