Extensions for reflection
The C++ Extensions for Reflection, ISO/IEC DTS 23619, specifies modifications to the core language and defines new components for the C++ standard library listed on this page.
The Reflection TS is based on the C++14 standard as modified by the Concepts TS.
Contents |
Core language changes
reflexpr-specifier
A reflexpr-specifier is of form reflexpr
(
reflexpr-operand )
, and specifies a meta-object type (see below).
reflexpr-operand can be one of following:
::
|
(1) | ||||||||
type-id | (2) | ||||||||
nested-name-specifier(optional) namespace-name | (3) | ||||||||
id-expression | (4) | ||||||||
( expression )
|
(5) | ||||||||
function-call-expression | (6) | ||||||||
functional-type-conv-expression | (7) | ||||||||
where function-call-expression is
postfix-expression ( expression-list(optional) )
|
(1) | ||||||||
and functional-type-conv-expression are following sorts of expressions which perform explict cast:
simple-type-specifier ( expression-list(optional) )
|
(1) | ||||||||
typename-specifier ( expression-list(optional) )
|
(2) | ||||||||
simple-type-specifier braced-init-list | (3) | ||||||||
typename-specifier braced-init-list | (4) | ||||||||
The operand to the reflexpr-specifier shall be a type, namespace, enumerator, variable, structured binding, data member, function parameter, captured entity, function-call-expression or functionaltype-conv-expression, and parenthesized expression. reflexpr(::) reflects the global namespace.
For a reflexpr-operand of form (
expression )
, the expression shall be a (possibly multi-parenthesized) function-call-expression or functional-type-conv-expression.
If a unparenthesized operand can be treated as either a type-id or a functional-type-conv-expression, then it is treated as a type-id. Parenthesizes can be used for disambiguation between function-style cast and a type-id. For example, given a class type X
with default constructor, reflexpr(X()) reflects the function type X(), and reflexpr((X())) reflects the expression X().
If the operand designates both an alias and a class name, the type represented by the reflexpr-specifier reflects the alias and satisfies reflect::Alias
.
If the operand designates a name whose declaration is enclosed in a block scope and the named entity is neither captured nor a function parameter, the program is ill-formed.
Meta-object types
A meta-object type is an unnamed, incomplete namespace-scope class type. A type satisfies the concept reflect::Object
if and only if it is a meta-object type. Meta-object types may satisfy other reflects, depending on the operand to reflexpr
.
It is unspecified whether repeatedly applying reflexpr
to the same operand yields the same type or a different type. If a meta-object type reflects an incomplete class type, certain type transformations cannot be applied.
A meta-object type allows inspection of some properties of the operand to reflexpr
through type traits or type transformations on it.
Overload resolution
If the postfix-expression of the function-call-expression is of class type, i.e. e is of class type in the function-call-expression e(args), then the user-defined conversion function of the type of the postfix-expression (e) shall not be used. postfix-expression shall name a function that is the unique result of overload resolution if it is not of class type.
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
An alias is a name introduced by a typedef declaration, an alias-declaration, or a using-declaration.
An entity or alias B
is reflection-related to an entity or alias A
if
-
A
andB
are the same entity or alias, -
A
is a variable or enumerator andB
is the type ofA
, -
A
is an enumeration andB
is the underlying type ofA
, -
A
is a class andB
is a member or base class ofA
, -
A
is a non-template alias that designates the entityB
, -
A
is not the global namespace andB
is an enclosing class or namespace ofA
, -
A
is the parenthesized expression (B
), -
A
is a lambda capture of the closure typeB
, -
A
is the closure type of the lambda captureB
, -
B
is the type specified by the functional-type-conv-expressionA
, -
B
is the function selected by overload resolution for a function-call-expressionA
, -
B
is the return type, a parameter type, or function type of the functionA
, or -
B
is reflection-related to an entity or aliasX
andX
is reflection-related toA
.
Reflection-relation relationship is reflexive and transitive, but not symmetric.
Informally speaking, the case that B
is reflection-related to A
means that B
participates in the declaration or definition of A
.
Zero or more successive applications of type transformations that yield meta-object types to the type denoted by a reflexpr-specifier enable inspection of entities and aliases that are reflection-related to the operand; such a meta-object type is said to reflect the respective reflection-related entity or alias.
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
- An expression used as reflexpr-operand is an unevaluated expressions and potentially constant evaluated.
- For the purpose of determination of variables captured in a lambda expression by a capture-default, a
reflexpr
operand is not considered to be an unevaluated operand. - A function or variable of static storage duration reflected by meta-object type
T
is odr-used by the specialization std::experimental::reflect::get_pointer<T>, as if by taking the address of an id-expression nominating the function or variable. - There can be more than one definition of a meta-object type, as long as all operations on this type yield the same constant expression results.
- A type is dependent if it is denoted by a reflexpr-specifier, and the operand
- is a type-dependent expression or a (possibly parenthesized) functional-type-conv-expression with at least one type-dependent immediate subexpression, or
- designates a dependent type or a member of an unknown specialization or a value-dependent constant expression.
Keywords
Predefined feature testing macros
__cpp_reflection |
a value of at least 201902 indicates that the Reflection TS is supported (macro constant) |
Library support | |
Concepts | |
Defined in header
<experimental/reflect> | |
Defined in namespace
std::experimental::reflect | |
Defined in inline namespace
std::experimental::reflect::v1 | |
Meta-object operations | |
Defined in header
<experimental/reflect> | |
Defined in namespace
std::experimental::reflect | |
Defined in inline namespace
std::experimental::reflect::v1 | |
Library feature testing macros | |
Defined in header
<experimental/reflect> | |
__cpp_lib_reflection |
a value of at least 201902 indicates that the support library of the Reflection TS is supported (macro constant) |
This section is incomplete |
Satisfaction of concepts
The following table lists that whether a meta-object type reflecting an operand satisfies concepts introduced by the Reflection TS.
Category | reflexpr operands
|
Satisfied concepts |
---|---|---|
Type | class-name designating a union | reflect::Union
|
class-name designating a closure type | reflect::Lambda
| |
class-name designating a non-union class | reflect::Record
| |
enum-name | reflect::Enum
| |
template type-parameter | reflect::Type , reflect::Alias
| |
decltype-specifier | reflect::Type , reflect::Alias
| |
type-name introduced by a using-declaration | reflect::Type , reflect::Alias , reflect::ScopedMember
| |
any other typedef-name | reflect::Type , reflect::Alias
| |
any other type-id | reflect::Type
| |
Namespace | namespace-alias | reflect::Namespace , reflect::Alias
|
any other namespace | reflect::Namespace
| |
Expression | the name of a data member | reflect::Variable
|
the name of a variable | reflect::Variable
| |
the name of an enumerator | reflect::Enumerator
| |
the name of a function parameter | reflect::FunctionParameter
| |
the name of a captured entity | reflect::LambdaCapture
| |
parenthesized expression | reflect::ParenthesizedExpression
| |
function-call-expression | reflect::FunctionCallExpression
| |
functional-type-conv-expression | reflect::FunctionalTypeConversion
|
reflexpr(::) satisfies reflect::GlobalNamespace
.
If the operand of the form id-expression is a constant expression, the type specified by the reflexpr-specifier also satisfies reflect::Constant
.
If the reflexpr-operand designates a class member, the type represented by the reflexpr-specifier also satisfies reflect::RecordMember
.
See also
contains some type’s information, the class returned by the typeid operator (class) | |
(C++11) |
Compile-time type information utilities |