Document #: | P1390R1 |
Date: | 2019-02-22 |
Project: | Programming Language C++ SG7/Evolution/LEWG/LWG/Core |
Reply-to: |
Matúš Chochlík <chochlik@gmail.com> Axel Naumann <Axel.Naumann@cern.ch> David Sankel <dsankel@bloomberg.net> |
This paper contains proposed resolutions to national body comments issued in [N5325] which summarizes responses to [N4766], the proposed Reflection TS.
See GB 086.
Reject, an alias-declaration is not a namespace-alias.
Recommend to reject the proposed change. The term alias can also refer to variable aliases.
Clarify by modifying the example in 21.12.3.4:
namespace N {
struct A;
}
namespace M {
using X = N::A;
}
+ struct B {
+ int i;
+ };
+ struct C {
+ using B::i;
+ };
using M_X_t = reflexpr(M::X);
using M_X_scope_t = get_scope_t<M_X_t>;
+ using C_i_t = reflexpr(C::i);
+ using C_i_scope_t = get_scope_t<C_i_t>;
The scope reflected by
M_X_scope_t
isM
, notN
; the scope reflected byC_i_scope_t
isC
, notB
.
Recommend to accept the proposed change with modification.
In 8.6, insert a new bullet 8.5, adjusting the subsequent bullet numbers:
(8) An expression is potentially constant evaluated if it is: … :::add (8.5) — a reflexpr-operand, :::
Modify 10.1.7.6 as follows:
Any other reflexpr-operand renders the program ill-formed.
If the reflexpr-operand of the form id-expression is a constant expression, the type specified by the reflexpr-specifier also satisfies
reflect::Constant
.
(Note that the example provided as part of CA 008 is invalid as reflexpr(foo(a))
specifies a type that satisfies FunctionCallExpression
, not Constant
.)
Recommend to accept the proposed change with modifications. Modify
Modify the new final paragraph of 10.1.7.2 as follows:
For a reflexpr-operand
x
, the type denoted byreflexpr(x)
isan implementation-defineda type that satisfies the constraints laid out in 10.1.7.6.
Modify 10.1.7.6 as follows:
(1) … A meta-object type is an unnamed, incomplete namespace-scope class type (Clause 12).
…
The type specified by the reflexpr-specifier is implementation-defined.
Propose to accept; this grammar is now allowed as part of id-expression, see CA 011.
Recommend to accept the proposed change.
Modify 10.1.7.2 as follows:
reflexpr-operand:
::
type-idnested-name-specifieropt identifier
nested-name-specifieropt simple-template-idnested-name-specifieropt namespace-name
id-expression
Modify 10.1.7.6 as follows:
For an operand that is a parenthesized expression (8.4.3), the type satisfies
reflect::ParenthesizedExpression
. For a parenthesized expression(E)
, whether or not itself nested inside a parenthesized expression, the expressionE
shall be either a parenthesized expression, a function-call-expression or a functional-type-conv-expression; otherwise the program is ill-formed.For an operand of the form function-call-expression, the type satisfies
reflect::FunctionCallExpression
. If the postfix-expression of the function-call-expression is of class type, the function call shall not resolve to a surrogate call function (16.3.1.1.2). Otherwise, the postfix-expression shall name a function that is the unique result of overload resolution.For an operand of the form functional-type-conv-expression (8.5.1.3), the type satisfies
reflect::FunctionalTypeConversion
. [ Note: The usual disambiguation between function-style cast and a type-id (11.2) applies. [ Example: The default constructor of classX
can be reflected on asreflexpr((X()))
, whilereflexpr(X())
reflects the type of a function returningX
. — end example ] — end note ]For an operand of the form identifier where identifier is a template type-parameter, the type satisfies both
reflect::Type
andreflect::Alias
.
The identifier or simple-template-id is looked up using the rules for name lookup (6.4): if a nested-name-specifier is included in the operand, qualified lookup (6.4.3) of nested-name-specifier identifier or nested-name-specifier simple-template-id will be performed, otherwise unqualified lookup (6.4.1) of identifier or simple-template-id will be performed.The type specified by the reflexpr-specifier satisfies concepts depending on the result ofthename lookup, as shown in Table 12.
If the reflexpr-operand designates a type-id not explicitly mentioned in Table 12, the type represented by the reflexpr-specifier satisfiesAny other reflexpr-operand renders the program ill-formed.reflect::Type
.
Modify the caption of Table 12 as follows:
reflect
concept (21.12.3) that the type specified by a reflexpr-specifier satisfies, for a given reflexpr-operandidentifier or simple-template-id.
Replace Table 12 by the following table:
Category | reflexpr-operand | reflect Concept |
---|---|---|
Type | class-name designating a union | reflect::Record |
class-name designating a closure type | reflect::Lambda |
|
class-name designating a non-union class | reflect::Class |
|
enum-name | reflect::Enum |
|
template type-parameter | both reflect::Type and reflect::Alias |
|
type-name introduced by a using-declaration | both reflect::Type and reflect::Alias |
|
any other typedef-name | both reflect::Type and reflect::Alias |
|
any other type-id | reflect::Type |
|
Namespace | namespace-alias | both reflect::Namespace and reflect::Alias |
any other namespace-name | reflect::Namespace |
|
Expression | the name of a data member | reflect::Variable |
the name of a variable or structured binding | 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; see Note A, below | reflect::ParenthesizedExpression |
|
function-call-expression; see Note B, below | reflect::FunctionCallExpression |
|
functional-type-conv-expression; see Note C, below | reflect::FunctionalTypeConversion |
Add the following new paragraph after the table:
Note A) For a parenthesized expression
(E)
, whether or not itself nested inside a parenthesized expression, the expressionE
shall be either a parenthesized expression, a function-call-expression, or a functional-type-conv-expression; otherwise the program is ill-formed.Note B) If the postfix-expression of the function-call-expression is of class type, the function call shall not resolve to a surrogate call function (16.3.1.1.2). Otherwise, the postfix-expression shall name a function that is the unique result of overload resolution.
Note C) [ Note: The usual disambiguation between function-style cast and a type-id (11.2) applies. [ Example: The default constructor of class
X
can be reflected on asreflexpr((X()))
, whilereflexpr(X())
reflects the type of a function returningX
. — end example ] — end note ]
Recommend to accept the proposed change.
Modify 10.1.7.6 as follows:
If the reflexpr-operand designates an entity or alias at block scope (6.3.3) or function
prototypeparameter scope (6.3.4) and…
Recommend to accept the propsed change; Constant
reflexpr-operands are now explicitly called out by the recommended modifications in CA 011. Also modify 21.12.3.17 as follows:
Constant
is true if and only if T reflects a constant expression (8.6)an enumerator or aconstexpr
variable.
Recommend to accept the proposed change. Similar to types represented by the decltype
specifier, fundamental and cv-qualified types must not have a scope either. Only declarations should be ScopeMember
s.
Modify Table 12 as follows:
decltype-specifier both reflect::Type
andreflect::Alias
type-name introduced by a using-declaration reflect::Type
and,reflect::Alias
, andreflect::ScopeMember
Modify 21.12.2 as follows:
- template <class T> concept Enum; // refines Type and Scope
- template <class T> concept Record; // refines Type and Scope
+ template <class T> concept Enum; // refines Type, Scope, and ScopeMember
+ template <class T> concept Record; // refines Type, Scope, and ScopeMember
template <class T> concept Scope; // refines Object
- template <class T> concept Type; // refines Named and ScopeMember
+ template <class T> concept Type; // refines Named
Modify 21.12.3.16 as follows:
- template <class T> concept Type = Named<T> && ScopeMember<T> && see below;
+ template <class T> concept Type = Named<T> && see below;
Add a note at the end of 21.12.3.16:
[ Note: Some types
T
also satisfyScopeMember
; others, for instance those reflecting cv-qualified types or fundamental types, do not. — end note ]
Recommend to accept the proposed change. Modify 10.1.7.6 as follows:
For a parenthesized expression
(E)
, whether or not itself nested inside a parenthesized expression, the expressionE
shall be either a parenthesized expression, a function-call-expression or a functional-type-conv-expression; otherwise the program is ill-formed.For a reflexpr-operand that is a parenthesized expression
(E)
,E
shall be a function-call-expression, functional-type-conv-expression, or an expression(E')
that satisfies the requirements for being a reflexpr-operand.
Recommend to accept the proposed change with modification. Modify 10.1.7.6 as follows:
An entity or alias
A
B
is reflection-related to an entity or aliasB
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 a class nested inB
(12.2.5),A
is not the global namespace andB
is an enclosing class or namespace ofA
,B
A
is the parenthesized expression(
A
B
)
,A
is a lambda capture of the closure typeB
,A
is the closure type of the lambda captureB
,A
B
is the type specified by the functional-type-conv-expressionB
A
,A
B
is the function selected by overload resolution for a function-call-expressionB
A
,A
B
is the return type, parameter type, or function type of the functionB
A
, orA
B
is reflection-related to an entity or aliasX
andX
is reflection-related toB
A
.
Note: the modification to the suggested change consists in the clarification of enclosing classes, and the removal of the superfluous nested class case. The latter is subsumed by “member or base class of A
”. The resolution was also modified to be such that A
yields B
, with a corresponding change in the position of A
and B
in the definition of the relation.
Recommend to accept with modification. The intent is to disallow the following:
int x;
void f() {
extern int x;
reflexpr(x); // ERROR
}
See the modification in US 025.
Recommend to accept proposal with modification:
Modify 10.1.7.6 as follows (assuming acceptance of the proposed resolution of US 024):
If the reflexpr-operand designates
an entity or alias declared ata name whose declaration is enclosed in a block scope (6.3.3) or function prototype scope (6.3.4) and the named entity is neither captured nor a function parameter, the program is ill-formed.
Recommend to accept to proposed modification of 17.7.2.1:
- denoted by
reflexpr(
operand)
, where operand designates a dependent type or a member of an unknown specialization or a value-dependent constant expression.
Recommend to accept the proposed modification of 17.7.2.1.
Add a new bullet after 9.9:
- denoted by
reflexpr(
operand)
, where operand is a type-dependent expression or a (possibly parenthesized) functional-type-conv-expression with at least one type-dependent immediate subexpression, or
Recommend to reject the proposed modification, as inline
is not needed (has no actual effect).
Recommend to accept the proposed change.
Modify 21.12.3.6 as follows:
- template <class T> concept Enumerator = Typed<T> && ScopeMember<T> && see below;
+ template <class T> concept Enumerator = Constant<T> && see below;
Modify 21.12.3.7 as follows:
- template <class T> concept Variable = Typed<T> && see below;
+ template <class T> concept Variable = Typed<T> && ScopeMember<T> && see below;
Modify 21.12.3.9 as follows:
- template <class T> concept Typed = Named<T> && see below;
+ template <class T> concept Typed = Object<T> && see below;
Modify 21.12.3.10 as follows:
- template <class T> concept Namespace = Scope<T> && see below;
+ template <class T> concept Namespace = Named<T> && Scope<T> && see below;
Modify 21.12.3.17 as follows:
- template <class T> concept Constant = ScopeMember<T> && Typed<T> && see below;
+ template <class T> concept Constant = Typed<T> && ScopeMember<T> && see below;
Modify 21.12.3.20 as follows (for consistency’s sake):
- template <class T> concept Callable = ScopeMember<T> && Scope<T> && see below;
+ template <class T> concept Callable = Scope<T> && ScopeMember<T> && see below;
Modify 21.12.3.25 as follows (for consistency’s sake):
- template <class T> concept Function = Callable<T> && Typed<T> && see below;
+ template <class T> concept Function = Typed<T> && Callable<T> && see below;
Modify 21.12.3.31 as follows (for consistency’s sake):
- template <class T> concept ConversionOperator = Operator<T> && MemberFunction<T> && see below;
+ template <class T> concept ConversionOperator = MemberFunction<T> && Operator<T> && see below;
Recommend to accept the proposed change with modifications.
Modify 21.12.3.4 as follows:
(2)
Except for the type represented by theType transformations (21.12.4) never yield anreflexpr
operator,Alias
properties resulting from type transformations (21.12.4) are not retained.Alias
; instead, they yield the aliased entity.
At the end of the paragraph 2 of 21.12.4, add
Alias entities are not returned by meta-object operations (21.12.3.4).
Modify 21.12.4.7 as follows:
(1) A specialization of any of these templates with a meta-object type that is reflecting an incomplete type renders the program ill-formed. Such errors are not in the immediate context (17.9.2). Members introduced by using-declarations (10.3.3) are included in the sequences below where applicable; the
Scope
of these members remains that of the declaration of the referenced entity. [ Note: These members are notAliase
s, see 21.12.4. A member injected into a derived class may have different access. — end note ]
(2) The nested type named
type
is an alias to anObjectSequence
specialized withRecordMember
types that reflect the following subset of direct non-template members of the class reflected byT
:
Recommend to accept the proposed change with modification; variable templates have no immediate context which would allow them to be SFINAEd on.
Modify 21.12.2 as follows:
template <class T>
+ requires RecordMember<T> || Base<T>
constexpr auto is_public_v = is_public<T>::value;
template <class T>
+ requires RecordMember<T> || Base<T>
constexpr auto is_protected_v = is_protected<T>::value;
template <class T>
+ requires RecordMember<T> || Base<T>
constexpr auto is_private_v = is_private<T>::value;
template <class T>
+ requires Variable<T> || Callable<T>
constexpr auto is_constexpr_v = is_constexpr<T>::value;
template <class T>
+ requires Variable<T> || MemberFunction<T>
constexpr auto is_static_v = is_static<T>::value;
template <class T>
+ requires Class<T> || MemberFunction<T>
constexpr auto is_final_v = is_final<T>::value;
template <class T>
+ requires Constructor<T> || ConversionOperator<T>
constexpr auto is_explicit_v = is_explicit<T>::value;
template <class T>
+ requires Namespace<T> || Callable<T>
constexpr auto is_inline_v = is_inline<T>::value;
template <class T>
+ requires Base<T> || MemberFunction<T> || Destructor<T>
constexpr auto is_virtual_v = is_virtual<T>::value;
template <class T>
+ requires MemberFunction<T> || Destructor<T>
constexpr auto is_pure_virtual_v = is_pure_virtual<T>::value;
template <class T>
+ requires Variable<T> || Function<T>
constexpr auto get_pointer_v = get_pointer<T>::value;
Recommend to reject. As 21.12.3.27 notes:
Some types that satisfy
Constructor
also satisfySpecialMemberFunction
.
The definition of SpecialMemberFunction
(21.12.3.27) uses “special member function (Clause 15)” and thus clearly includes special member functions that are constructors.
Recommend to reject the proposed change of renaming the concept Object
to Metaobject
:
The meta-nature of std::reflect::Object
is stated by the namespace it is defined in. There is no need to repeat this meta-nature by prepending “Meta”.
See CA 030.
Recommend to accept the proposed modification by adding the following note to 21.12.3:
[ Note: unlike
std::is_enum
,std::reflect::is_enum
operates on meta-object types. — end note ]
See CA 030.
Suggest to reject.
This is a misunderstanding. A ‘base’ in this case has a class which is accessible with get_class
. This class then has a name.
See CA 030.
See CA 030.
See resolution to CA 071.
Note: the resolution here should be should also be applied to [P1208R3].
Recommend to accept the proposed change, with modifications: the file name should not be represented as an NTMBS but NTBS since multi-byte has encoding implications.
Modify 21.12.4.3 as follows:
(2) All specializations of
get_name<T>
andget_display_name<T>
shall meet theUnaryTypeTrait
requirements (23.15.1) with a static data member namedvalue
of typeconst char (&)[N]
, referencing a static, constant expression character array (NTBSNTMBS) of lengthN
, as if declared asstatic constexpr char STR[N] = ...;
.
Note: the resolution here should be should also be applied to [P1208R3].
It is unclear how (or if) such a thing can be implemented. At any rate, this is something that can be added in the future if we get implementation experience that suggests this is possible and desirable.
Recommend to accept with modification:
In 21.12.4.1, apply the following changes:
(3) … representing some offset from the start of the line (for
get_source_column<T>
) ofthe most recenta declaration of the entity or typedef described byT
.
(4) … The value of the NTBS is the presumed name of the source file (19.8) of
the most recenta declaration of the entity or typedef described byT
.
This matches US 024 forbidding block-scope declarations as reflexpr-operands.
Recommend to accept the proposed modification, by applying the following change to 21.12.4.10:
(1) … The nested type named
type
is an alias todesignatesreflexpr(X)
, whereX
is the base class (without retaining possibleAlias
properties, see 21.12.3.4) reflected byT
.
Also apply the change
nested type named
type
thatis an alias todesignates
for all occurrences in the document.
reflexpr((X(X())))
does not invoke the copy constructor, due to guaranteed copy elision. An alternative approach to access constructors through an expression is reflexpr((X(declval<X&>())))
. A more reliable approach is to retrieve a class’s constructors, take the subset of special member functions, and find the copy constructor back.
We believe that no normative change is needed to address this NB comment. To clarify the intent, we recommend to accept the proposed change, adding the following note at the end of 21.12.4.16:
[ Note:
get_constructor_t<get_subexpression_t<reflexpr((T(T())))>>
is ill-formed because the functional-type-conv expression does not perform overload resolution for a constructor (15.8.3). — end note ]
NOTE TO THE EDITOR: this Note shall be dropped when rebasing on C++14.
Recommend to accept the proposed change with modification.
Modify 21.12.4.16 as follows:
For a
type conversionfunctional-type-conv-expression reflected byT
,the nested type namedlettype
S
be the type specified by the type conversion (8.5.1.3 [expr.type.conv]). If a constructor is used for the initialization ofS
, the typeget_constructor<T>::type
is theConstructor
reflectingthe constructor of the type specified by the type conversion, as selected by overload resolution. The program is ill-formed if no such constructor exists.that constructor; otherwise,get_constructor<T>
has no member namedtype
. [ Note: For example, fundamental types (6.7.1) do not have constructors. — end note ]
Recommend to accept.
(1) All specializations of these templates shall meet the
UnaryTypeTrait
requirements (23.15.1). If their template parameter reflects a member function that isstatic
(foris_static
),const
(foris_const
),volatile
(foris_volatile
), declared with a ref-qualifier&
(forhas_lvalueref_qualifier
) or&&
(forhas_rvalueref_qualifier
), implicitly or explicitlyvirtual
(foris_virtual
), pure virtual (foris_pure_virtual
), ormarked withoverrides a member function of a base class (foroverride
is_override
) orfinal
(foris_final
), the base characteristic of the respective template specialization istrue_type
, otherwise it isfalse_type
.
Recommend to reject.
This is already the existing behavior and lambda objects are specifically called out. See Section 21.12.4.3 paragraph 2.5. Lambda objects are not unnamed entities.
Recommend to accept, see the resolution to CA 071.
Template aliases are not supported by N4766.
Recommend to accept, by applying the modification shown in CA 071.
See CH 058.
Recommend to accept, by applying the following modification to 21.12.4.3:
(2.4.6) - for
T
reflectingall other simple-type-specifiersa cv-unqualified fundamental type other thanstd::nullptr_t
, the name stated in the “Type” column of Table 9 in (10.1.7.2);
Recommend to accept CA 065 and CA 066, both with modifications.
See the resolution to CA 071.
See CH 058.
Recommend to accept: struct
and class
are conceptually the same, and std::reflect::is_struct
wrongly suggests the need of std::is_struct
. To clearly distinguish the std::is_class
type trait from these meta functions, we recommend to rename them as proposed in the NB comment.
Apply the following modification to 21.12.2:
- template <Type T> struct is_class;
+ template <Class T> struct uses_class_key;
- template <Type T> struct is_struct;
+ template <Class T> struct uses_struct_key;
template <Type T> struct is_union;
template <Typed T>
using get_type_t = typename get_type<T>::type;
template <Type T>
using get_reflected_type_t = typename get_reflected_type<T>::type;
template <Type T>
constexpr auto is_enum_v = is_enum<T>::value;
- template <Type T>
- constexpr auto is_class_v = is_class<T>::value;
+ template <Class T>
+ constexpr auto uses_class_key_v = uses_class_key<T>::value;
- template <Type T>
- constexpr auto is_struct_v = is_struct<T>::value;
+ template <Class T>
+ constexpr auto uses_struct_key_v = uses_struct_key<T>::value;
Apply the following modification to 21.12.4.5:
template <
Type
Class
T> struct
is_class
uses_class_key
;
template <
Type
Class
T> struct
is_struct
uses_struct_key
;
(8) All specializations of
is_class
uses_class_key
<T>
andis_struct
uses_struct_key
<T>
shall meet theUnaryTypeTrait
requirements (23.15.1). IfT
reflects a classwithfor which all declarations use class-keyclass
(foris_class
uses_class_key
<T>
) orstruct
(foris_struct
uses_struct_key
<T>
), the base characteristic of the respective template specialization istrue_type
, otherwise it is. Iffalse_type
T
reflects a class for which no declaration uses class-keyclass
(foruses_class_key<T>
) orstruct
(foruses_struct_key<T>
), the base characteristic of the respective template specialization isfalse_type
. Otherwise, it is unspecified whether the base characteristic istrue_type
orfalse_type
.If the same class has redeclarations with both class-keyclass
and class-keystruct
, the base characteristic of the template specialization of exactly one ofis_class<T>
andis_struct<T>
can betrue_type
, the other template specialization isfalse_type
; the actual choice of value is unspecified.
To allow future extensions of template reflection, we recommend to accept this comment with modification.
To represent the scope of template parameters also for variable templates, a new concept needs to be introduced, serving as the scope of template parameters. For the time being, this concept has no operations (beyond that of Object
) defined.
Modify 21.12.2 as follows:
template <class T> concept ObjectSequence; // refines Object
+ template <class T> concept TemplateParameterScope; // refines Scope
template <class T> concept Named; // refines Object
Add a new paragraph 21.12.3.3, moving the existing 21.12.3.3 to 21.12.3.4, etc:
21.12.3.3 Concept
TemplateParameterScope
template <class T> concept TemplateParameterScope = Scope<T> &&
see below
;
TemplateParameterScope<T>
istrue
if and only ifT
is aScope
reflecting the scope of a template type-parameter, generated by a metaobject operation. [ Note: It represents the template parameter scope (6.3.9), providing a scope to theAlias
reflecting a template type-parameter. — end note ].
Modify 21.12.3.4 as follows:
[Note: The
Scope
of anAlias
is the scope that the alias was injected into. For anAlias
reflecting a template type-parameter, that scope is itsTemplateParameterScope
. — end note ]
Add the following sentence to the end of 21.12.4.6, paragraph 2:
(2) … For a template type-parameter, this innermost scope is the
TemplateParameterScope
representing the template parameter scope in which it has been declared.
Recommend to accept the proposed change, by modifying 21.12.4.6 as follows:
(2) … class scope, enumeration scope, function scope
(in the case where the function’s parameters), or …
Recommend to accept the proposed change.
Modify 21.12.4.7 as follows:
(2) … The nested type named
type
is an alias to andesignates a meta-object type satisfyingObjectSequence
specialized withRecordMember
types thatObjectSequence
, containing elements which satisfyRecordMember
and reflect the following subset of non-template members of the class reflected byT
:
(5) … The nested type named
type
is an alias to andesignates a meta-object type satisfyingObjectSequence
specialized withRecordMember
types thatObjectSequence
, containing elements which satisfyRecordMember
and reflect the following subset of function members of the class reflected byT
:
(10) … The nested type named
type
is an alias to andesignates a meta-object type satisfyingObjectSequence
specialized withType
types thatObjectSequence
, containing elements which satisfyType
and reflect the following subset of types declared in the class reflected byT
:
(13) … The nested type named
type
is an alias to andesignates a meta-object type satisfyingObjectSequence
specialized withBase
types thatObjectSequence
, containing elements which satisfyBase
and reflect the following subset of base classes of the class reflected byT
:
Modify 21.12.4.8 as follows:
(2) … The nested type named
type
is an alias to andesignates a meta-object type satisfyingObjectSequence
specialized withEnumerator
types thatObjectSequence
, containing elements which satisfyEnumerator
and reflect the enumerators of the enumeration type reflected byT
. …
Modify 21.12.4.13 as follows:
(1) … The nested type named
type
is an alias to andesignates a meta-object type satisfyingObjectSequence
specialized withFunctionParameter
types thatObjectSequence
, containing elements which satisfyFunctionParameter
and reflect the parameters of the function reflected byT
. …
Modify 21.12.4.23 as follows:
(1) … The nested type named
type
is an alias to andesignates a meta-object type satisfyingObjectSequence
specialized withLambdaCapture
types thatObjectSequence
, containing elements which satisfyLambdaCapture
and reflect the captures of the closure object reflected byT
. …
The lack of an interface to determine thread-local storage duration is surprising; we recommend to accept the proposed modification.
Modify 21.12.2 as follows:
template <Constant T> struct get_constant;
template <Variable T> struct is_constexpr<T>;
template <Variable T> struct is_static<T>;
+ template <Variable T> struct is_thread_local;
template <Variable T> struct get_pointer<T>;
template <Constant T>
constexpr auto get_constant_v = get_constant<T>::value;
+ template <Variable T>
+ constexpr auto is_thread_local_v = is_thread_local<T>::value;
Modify paragraph 4 of 21.12.4.9 as follows:
(3)
template <Variable T> struct is_static<T>;
(4)
template <Variable T> struct is_thread_local;
All specializations of
is_static<T>
andis_thread_local<T>
shall meet theUnaryTypeTrait
requirements (23.15.1). IfT
reflects a variable with static (foris_static
) or thread (foris_thread_local
) storage duration, the base characteristic of the respective template specialization istrue_type
, otherwise it isfalse_type
.
Recommend to accept the proposed change, by adding the following sentence at the beginning of paragraph 4:
(4)
All specializationsIfT
reflects a reference with static storage duration, and the reference has no prior initialization or has not been initialized with an object of static storage duration, the specialization ofget_pointer<T>
has no member namedtype
. Otherwise, the specialization ofget_pointer<T>
shall meet theUnaryTypeTrait
requirements (23.15.1),…
Recommend to accept the proposed change, by editing paragraph 1 in C.5.1 Clause 5: lexical conventions [diff.cpp17.lex]:
(1) Rationale: Required for new features. The
requires
keyword is added to introduce constraints through a requires-clause or a requires-expression. Theconcept
keyword is added to enable the definition of concepts (17.6.8). Thereflexpr
keyword is added to introduce meta-data through a reflexpr-specifier.Effect on original feature: Valid ISO C++ 2017 code using
concept
or,requires
, orreflexpr
as an identifier is not valid in this International Standard.
See CH 082.
See CH 013.
The authors believe that this comment should be addressed to CWG, rather than SG7/LEWG.
The authors recommend to add a new final sentence to the last paragraph of 10.1.7.6 as follows:
Reflecting directly or indirectly upon
std::align_val_t
[basic.stc.dynamic] without inclusion of the header<new>
is ill-formed; no diagnostic required.
Propose to accept the suggested modification, by inserting a new 4.3 between 4.2 and 4.3:
4.3 Feature-testing recommendations [intro.features]
(1) An implementation that provides support for this Technical Specification shall define the feature test macros in Table 2.
Macro name Value Header __cpp_reflection 201902 none __cpp_lib_reflection 201902 <reflect>
Table 2 - Feature-test macro(s)
Suggestion to accept this request.
<experimental/reflect>
to Table 19 “C++ headers for freestanding implementations” referenced by 20.5.1.3.Modify definition of unpack_sequence_t
from [reflect.synopsis] as follows.
template <template <class...> class Tpl, ObjectSequence T>
- constexpr auto unpack_sequence_t = unpack_sequence<Tpl, T>::type;
+ using unpack_sequence_t = typename unpack_sequence<Tpl, T>::type;
Suggest to reject; insufficient motivation for a change.
Suggest to accept with modification.
See the resolution to CA 071.
Suggest to accept the proposed change with modifications; this is a non-editorial change.
Replace the bulleted list of 21.12.4.3/2 by the following:
The value of
get_display_name_v<T>
is the empty string ifT
reflects an unnamed entity; otherwise the value is implementation defined.The value of
get_name_v<T>
refers to a string literal whose s-char-sequence is obtained by the first matching case in the following list:
- for
T
reflecting an alias, the unqualified name of the aliasing declaration;- for
T
reflecting an unnamed entity, the empty string.- for
T
reflecting a specialization of a class, function (except for conversion functions, constructors, operator functions, or literal operators), or variable template, its template-name;- for
T
reflecting a cv-unqualified type that is
- a type-parameter, the identifier introduced by the type-parameter;
- a class type, its class-name;
- an enumeration type, its enum-name;
- a fundamental type other than
std::nullptr_t
, the name stated in the “Type” column of Table 9 in (10.1.7.2);- for
T
reflecting
- a namespace, its namespace-name;
- a variable, enumerator, data member, or function, its unqualified name;
- a function parameter, its name;
- a constructor, the injected-class-name of its class;
- a destructor, the injected-class-name of its class, prefixed by the character ’~’;
- an operator function, the operator element of the relevant operator-function-id;
- a literal operator, the s-char-sequence
\"\"
followed by the literal suffix identifier of the operator’s literal-operator-id;- a conversion function, the same characters as
get_name_v<R>
, withR
reflecting the type represented by the conversion-type-id.- In all other cases, the string’s value is the empty string.
Suggest to reject. It is clear enough as is.
Special thanks to Michael Park who is responsible for the pandoc extensions [PBLOG] used to create this paper.
[N4766] Matúš Chochlík, Axel Naumann, and David Sankel. 2018. Working Draft, C++ Extensions for Reflection.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4766.pdf
[N5325] Secretariat: ANSI (United States). 2018. Summary of Voting on PDTS 23619, Technical Specification – C++ Extensions for Reflection.
[P1208R3] Robert Douglas and Corentin Jabot. 2018. Source-Code Information Capture.
https://wg21.link/P1208R3
[PBLOG] Michael Park. 2018. How I format my C++ papers.
https://mpark.github.io/programming/2018/11/16/how-i-format-my-cpp-papers/