diff --git a/source/basic.tex b/source/basic.tex index 8178129463..e77e5a9b69 100644 --- a/source/basic.tex +++ b/source/basic.tex @@ -114,17 +114,33 @@ A \defn{variable} is introduced by the declaration of a reference other than a non-static data member or of -an object. The variable's name, if any, denotes the reference or object. +an object. \pnum -An \defn{entity} is a value, object, reference, +An \defn{entity} is a +variable, structured binding, result binding, -function, enumerator, type, -class member, bit-field, template, template specialization, namespace, or -pack. An entity $E$ is denoted by the name (if any) -that is introduced by a declaration of $E$ or -by a \grammarterm{typedef-name} introduced by a declaration specifying $E$. +function, +enumerator, +type, +type alias, +non-static data member, +bit-field, +template, +namespace, +namespace alias, +template parameter, +function parameter, or +\grammarterm{init-capture}. +The \defnadj{underlying}{entity} of an entity is that entity +unless otherwise specified. +A name \defnx{denotes}{denote} the underlying entity of +the entity declared by each declaration that introduces the name. +\begin{note} +Type aliases and namespace aliases have underlying entities +that are distinct from themselves. +\end{note} \pnum A \defnadj{local}{entity} is a variable with @@ -153,7 +169,7 @@ unit. If so, the declaration specifies the interpretation and semantic properties of these names. -A declaration of an entity or \grammarterm{typedef-name} $X$ is +A declaration of an entity $X$ is a redeclaration of $X$ if another declaration of $X$ is reachable from it\iref{module.reach}; otherwise, it is a \defnadj{first}{declaration}. @@ -222,12 +238,15 @@ \item it is an \grammarterm{alias-declaration}\iref{dcl.typedef}, \item it is -a -\grammarterm{using-declaration}\iref{namespace.udecl}, +a \grammarterm{namespace-alias-definition}\iref{namespace.alias}, +\item it is +a \grammarterm{using-declaration}\iref{namespace.udecl}, \item it is a \grammarterm{deduction-guide}\iref{temp.deduct.guide}, \item it is a \grammarterm{static_assert-declaration}\iref{dcl.pre}, +\item it is +a \grammarterm{consteval-block-declaration}, \item it is an \grammarterm{attribute-declaration}\iref{dcl.pre}, @@ -265,7 +284,6 @@ int X::y = 1; // defines \tcode{X::y} enum { up, down }; // defines \tcode{up} and \tcode{down} namespace N { int d; } // defines \tcode{N} and \tcode{N::d} -namespace N1 = N; // defines \tcode{N1} X anX; // defines \tcode{anX} \end{codeblock} @@ -276,6 +294,7 @@ int f(int); // declares \tcode{f} struct S; // declares \tcode{S} typedef int Int; // declares \tcode{Int} +namespace N1 = N; // declares \tcode{N1} extern X anotherX; // declares \tcode{anotherX} using N::d; // declares \tcode{d} \end{codeblock} @@ -369,8 +388,9 @@ The set of \defn{potential results} of an expression $E$ is defined as follows: \begin{itemize} -\item If $E$ is an -\grammarterm{id-expression}\iref{expr.prim.id}, the set +\item If $E$ is +an \grammarterm{id-expression}\iref{expr.prim.id} or +a \grammarterm{splice-expression}\iref{expr.prim.splice}, the set contains only $E$. \item If $E$ is a subscripting operation\iref{expr.sub} with an array operand, the set contains the potential results of that operand. @@ -396,17 +416,21 @@ \item Otherwise, the set is empty. \end{itemize} \begin{note} -This set is a (possibly-empty) set of \grammarterm{id-expression}{s}, +This set is a (possibly-empty) set of +\grammarterm{id-expression}{s} and \grammarterm{splice-expression}s, each of which is either $E$ or a subexpression of $E$. \begin{example} In the following example, the set of potential results of the initializer of \tcode{n} contains the first \tcode{S::x} subexpression, but not the second \tcode{S::x} subexpression. +The set of potential results of the initializer of \tcode{o} contains +the subexpression \tcode{[:\caret\caret S::x:]}. \begin{codeblock} struct S { static const int x = 0; }; const int &f(const int &r); int n = b ? (1, S::x) // \tcode{S::x} is not odr-used here : f(S::x); // \tcode{S::x} is odr-used here, so a definition is required +int o = [:^^S::x:]; \end{codeblock} \end{example} \end{note} @@ -454,7 +478,9 @@ \pnum \label{term.odr.use}% A variable is named by an expression -if the expression is an \grammarterm{id-expression} that denotes it. +if the expression is an \grammarterm{id-expression} or +\grammarterm{splice-expression}\iref{expr.prim.splice} +that designates it. A variable \tcode{x} that is named by a potentially-evaluated expression $N$ that appears at a point $P$ @@ -511,7 +537,12 @@ \end{example} \pnum -A structured binding is odr-used if it appears as a potentially-evaluated expression. +A structured binding is named by an expression +if that expression is either an \grammarterm{id-expression} or +a \grammarterm{splice-expression} +that designates that structured binding. +A structured binding is odr-used +if it is named by a potentially-evaluated expression. \pnum \tcode{*\keyword{this}} is odr-used if \keyword{this} appears as a potentially-evaluated expression @@ -697,7 +728,16 @@ \end{note} \pnum -For any definable item \tcode{D} with definitions in multiple translation units, +If a definable item \tcode{D} is defined in a translation unit +by an injected declaration $X$\iref{expr.const} and +another translation unit contains a definition of \tcode{D}, +that definition shall be an injected declaration +having the same characteristic sequence as $X$; +a diagnostic is required only if \tcode{D} is attached to a named module and +a prior definition is reachable at the point where a later definition occurs. + +\pnum +For any other definable item \tcode{D} with definitions in multiple translation units, \begin{itemize} \item if \tcode{D} is a non-inline non-templated function or variable, or @@ -723,7 +763,7 @@ is considered to consist of the sequence of tokens of the corresponding \grammarterm{lambda-expression}. \item In each such definition, corresponding names, looked up -according to~\ref{basic.lookup}, shall refer to the same entity, after +according to~\ref{basic.lookup}, shall denote the same entity, after overload resolution\iref{over.match} and after matching of partial template specializations\iref{temp.spec.partial.match}, except that a name can refer to \begin{itemize} @@ -739,7 +779,7 @@ \item a reference with internal or no linkage initialized with a constant expression such that -the reference refers to the same entity in all definitions of \tcode{D}. +the reference refers to the same object or function in all definitions of \tcode{D}. \end{itemize} \item In each such definition, except within @@ -768,11 +808,17 @@ \item In each such definition, a default argument used by an (implicit or explicit) function call or a default template argument used by an (implicit or explicit) -\grammarterm{template-id} or \grammarterm{simple-template-id} +\grammarterm{template-id}, +\grammarterm{simple-template-id}, or +\grammarterm{splice-specialization-specifier} is treated as if its token sequence were present in the definition of \tcode{D}; that is, the default argument or default template argument is subject to the requirements described in this paragraph (recursively). + +\item In each such definition, +corresponding \grammarterm{reflect-expression}s\iref{expr.reflect} +compute equivalent values\iref{expr.eq}. \end{itemize} \pnum @@ -927,6 +973,9 @@ Any names (re)introduced by a declaration are \defnx{bound}{name!bound} to it in its target scope. \end{itemize} +The \defnadj{host}{scope} of a declaration is +the inhabited scope if that scope is a block scope and +the target scope otherwise. An entity \defnx{belongs}{entity!belong} to a scope $S$ if $S$ is the target scope of a declaration of the entity. \begin{note} @@ -1007,7 +1056,7 @@ \item either is a \grammarterm{using-declarator}, or \item -one declares a type (not a \grammarterm{typedef-name}) and the other declares a +one declares a type (not a type alias) and the other declares a variable, non-static data member other than of an anonymous union\iref{class.union.anon}, enumerator, @@ -1664,7 +1713,7 @@ In certain contexts, only certain kinds of declarations are included. After any such restriction, any declarations of classes or enumerations are discarded if any other declarations are found. \begin{note} -A type (but not a \grammarterm{typedef-name} or template) +A type (but not a type alias or template) is therefore hidden by any other entity in its scope. \end{note} \indextext{type-only!lookup|see{lookup, type-only}}% @@ -1672,8 +1721,8 @@ only declarations of types and templates whose specializations are types are considered; furthermore, if declarations -of a \grammarterm{typedef-name} and of the type to which it refers are found, -the declaration of the \grammarterm{typedef-name} is discarded +of a type alias and of its underlying entity are found, +the declaration of the type alias is discarded instead of the type declaration. \rSec2[class.member.lookup]{Member name lookup}% @@ -2137,7 +2186,16 @@ The set of entities is determined in the following way: \begin{itemize} -\item If \tcode{T} is a fundamental type, its associated set of +\item If \tcode{T} is \tcode{std::meta::info}\iref{meta.reflection.synop}, +its associated set of entities is the singleton containing +the enumeration type \tcode{std::meta::operators}\iref{meta.reflection.operators}. +\begin{note} +The \tcode{std::meta::info} type is a type alias, +so an explicit rule is needed to associate calls +whose arguments are reflections with the namespace \tcode{std::meta}. +\end{note} + +\item If \tcode{T} is any other fundamental type, its associated set of entities is empty. \item If \tcode{T} is a class type (including unions), @@ -2295,8 +2353,14 @@ followed by a \tcode{::} scope resolution operator considers only namespaces, types, and templates whose specializations are types. -If a name, \grammarterm{template-id}, or \grammarterm{computed-type-specifier} +If a +name, +\grammarterm{template-id}, +\grammarterm{splice-scope-specifier}, or +\grammarterm{computed-type-specifier} is followed by a \tcode{::}, +it shall either be +a dependent \grammarterm{splice-scope-specifier}\iref{temp.dep.splice} or it shall designate a namespace, class, enumeration, or dependent type, and the \tcode{::} is never interpreted as a complete \grammarterm{nested-name-specifier}. @@ -2345,6 +2409,7 @@ \item a \grammarterm{typename-specifier}, \item a \grammarterm{qualified-namespace-specifier}, or \item a \grammarterm{nested-name-specifier}, +\grammarterm{reflection-name}, \grammarterm{elaborated-type-specifier}, or \grammarterm{class-or-decltype} that has a \grammarterm{nested-name-specifier}\iref{expr.prim.id.qual}. @@ -2739,6 +2804,70 @@ only namespace names are considered.% \indextext{lookup!name|)}% +\rSec1[basic.splice]{Splice specifiers} +\indextext{splice|(}% + +\begin{bnf} +\nontermdef{splice-specifier}\br + \terminal{[:} constant-expression \terminal{:]} +\end{bnf} + +\begin{bnf} +\nontermdef{splice-specialization-specifier}\br + splice-specifier \terminal{<} \opt{template-argument-list} \terminal{>} +\end{bnf} + +\pnum +The \grammarterm{constant-expression} of a \grammarterm{splice-specifier} +shall be a converted constant expression of +type \tcode{std::meta::info}\iref{expr.const}. +A \grammarterm{splice-specifier} +whose converted \grammarterm{constant-expression} represents +a construct $X$ is said to \defn{designate} either +\begin{itemize} +\item the underlying entity of $X$ if $X$ is an entity\iref{basic.pre}, or +\item $X$ otherwise. +\end{itemize} +\begin{note} +A \grammarterm{splice-specifier} is dependent +if the converted \grammarterm{constant-expression} is +value-dependent\iref{temp.dep.splice}. +\end{note} + +\pnum +A non-dependent \grammarterm{splice-specifier} of +a \grammarterm{splice-specialization-specifier} shall designate a template. + +\pnum +\begin{note} +A \tcode{<} following a \grammarterm{splice-specifier} is interpreted as +the delimiter of a \grammarterm{template-argument-list} +when the \grammarterm{splice-specifier} is preceded by +the keyword \keyword{template} or the keyword \keyword{typename}, or +when it appears in a type-only context\iref{temp.names}. +\begin{example} +\begin{codeblock} +constexpr int v = 1; +template struct TCls { + static constexpr int s = V + 1; +}; + +using alias = [:^^TCls:]<([:^^v:])>; + // OK, a \grammarterm{splice-specialization-specifier} with a \grammarterm{splice-expression} as a template argument + +static_assert(alias::s == 2); + +auto o1 = [:^^TCls:]<([:^^v:])>(); // error: < means less than +auto o2 = typename [:^^TCls:]<([:^^v:])>(); // OK, o2 is an object of type TCls<1> + +consteval int bad_splice(std::meta::info v) { + return [:v:]; // error: v is not constant +} +\end{codeblock} +\end{example} +\end{note} +\indextext{splice|)} + \rSec1[basic.link]{Program and linkage}% \indextext{linkage|(} @@ -2910,6 +3039,8 @@ \item they appear in the same translation unit, or \item +they both declare type aliases or namespace aliases that have the same underlying entity, or +\item they both declare names with module linkage and are attached to the same module, or \item they both declare names with external linkage. @@ -3022,6 +3153,16 @@ \item $D$ contains a \grammarterm{lambda-expression} whose closure type is $E$, \item +$D$ contains +a \grammarterm{reflect-expression} or a \grammarterm{splice-specifier} +that, respectively, represents or designates $E$, +\item +$D$ is an injected declaration\iref{expr.const} +whose characteristic sequence contains a reflection +that represents +a data member description ($T$, $N$, $A$, $W$, $\mathit{NUA}$)\iref{class.mem.general} +for which $T$ is $E$, +\item $E$ is not a function or function template and $D$ contains an \grammarterm{id-expression}, \grammarterm{type-specifier}, @@ -3070,7 +3211,7 @@ An entity is \defnx{TU-local}{TU-local!entity} if it is \begin{itemize} \item -a type, function, variable, or template that +a type, type alias, namespace, namespace alias, function, variable, or template that \begin{itemize} \item has a name with internal linkage, or @@ -3102,14 +3243,28 @@ A value or object is \defnx{TU-local}{TU-local!value or object} if either \begin{itemize} \item +it is of TU-local type, +\item it is, or is a pointer to, -a TU-local function or the object associated with a TU-local variable, or +a TU-local function or the object associated with a TU-local variable, \item it is an object of class or array type and any of its subobjects or any of the objects or functions to which its non-static data members of reference type refer -is TU-local and is usable in constant expressions. +is TU-local and is usable in constant expressions, or +\item +it is a reflection value\iref{basic.fundamental} that represents +\begin{itemize} +\item +an entity, value, or object that is TU-local, +\item +a direct base class relationship (\tcode{D}, \tcode{B})\iref{class.derived.general} +for which either \tcode{D} or \tcode{B} is TU-local, or +\item +a data member description ($T$, $N$, $A$, $W$, $\mathit{NUA}$)\iref{class.mem.general} +for which $T$ is TU-local. +\end{itemize} \end{itemize} \pnum @@ -3159,6 +3314,16 @@ void adl(double); inline void h(auto x) { adl(x); } // OK, but certain specializations are exposures + +constexpr std::meta::info r1 = ^^g<0>; // OK +namespace N2 { + static constexpr std::meta::info r2 = ^^g<1>; // OK, \tcode{r2} is TU-local +} +constexpr std::meta::info r3 = ^^f; // error: \tcode{r3} is an exposure of \tcode{f} + +constexpr auto ctx = std::meta::access_context::current(); +constexpr std::meta::info r4 = + std::meta::members_of(^^N2, ctx)[0]; // error: \tcode{r4} is an exposure of \tcode{N2::r2} \end{codeblocktu} \begin{codeblocktu}{Translation unit \#2} module A; @@ -5022,7 +5187,7 @@ \label{term.scalar.type}% Arithmetic types\iref{basic.fundamental}, enumeration types, pointer types, pointer-to-member types\iref{basic.compound}, -\tcode{std::nullptr_t}, +\tcode{std::meta::\brk{}info}, \tcode{std::nullptr_t}, and cv-qualified\iref{basic.type.qualifier} versions of these types are collectively called @@ -5094,6 +5259,21 @@ layout-compatible enumerations\iref{dcl.enum}, or layout-compatible standard-layout class types\iref{class.mem}. +\pnum +A type is \defn{consteval-only} if it is either +\tcode{std::meta::info} or +a type compounded from a consteval-only type\iref{basic.compound}. +Every object of consteval-only type shall be +\begin{itemize} +\item +the object associated with a constexpr variable or a subobject thereof, +\item +a template parameter object\iref{temp.param} or a subobject thereof, or +\item +an object whose lifetime begins and ends +during the evaluation of a core constant expression. +\end{itemize} + \rSec2[basic.fundamental]{Fundamental types} \pnum @@ -5400,6 +5580,94 @@ pointer-to-member conversions\iref{conv.ptr,conv.mem}. \tcode{\keyword{sizeof}(std::nullptr_t)} shall be equal to \tcode{\keyword{sizeof}(\keyword{void}*)}. +\pnum +A value of type \tcode{std::meta::info} is called a \defn{reflection}. +There exists a unique \defnadj{null}{reflection}; +every other reflection is a representation of +\begin{itemize} +\item a value of scalar type\iref{temp.param}, +\item an object with static storage duration\iref{basic.stc}, +\item a variable\iref{basic.pre}, +\item a structured binding\iref{dcl.struct.bind}, +\item a function\iref{dcl.fct}, +\item an enumerator\iref{dcl.enum}, +\item a type alias\iref{dcl.typedef}, +\item a type\iref{basic.types}, +\item a class member\iref{class.mem}, +\item an unnamed bit-field\iref{class.bit}, +\item a class template\iref{temp.pre}, +\item a function template, +\item a variable template, +\item an alias template\iref{temp.alias}, +\item a concept\iref{temp.concept}, +\item a namespace alias\iref{namespace.alias}, +\item a namespace\iref{basic.namespace.general}, +\item a direct base class relationship\iref{class.derived.general}, or +\item a data member description\iref{class.mem.general}. +\end{itemize} +A reflection is said to \defn{represent} the corresponding construct. +\begin{note} +A reflection of a value can be produced by library functions such as +\tcode{std::meta::constant_of} and \tcode{std::meta::reflect_constant}. +\end{note} +\begin{example} +\begin{codeblock} +int arr[] = {1, 2, 3}; +auto [a1, a2, a3] = arr; +void fn(); +enum Enum { A }; +using Alias = int; +struct B {}; +struct S : B { + int mem; + int : 0; +}; +template struct TCls {}; +template void TFn(); +template int TVar; +template concept Concept = requires { true; }; +namespace NS {}; +namespace NSAlias = NS; + +constexpr auto ctx = std::meta::access_context::current(); + +constexpr auto r1 = std::meta::reflect_constant(42); // represents int value of 42 +constexpr auto r2 = std::meta::reflect_object(arr[1]); // represents int object +constexpr auto r3 = ^^arr; // represents a variable +constexpr auto r4 = ^^a3; // represents a structured binding +constexpr auto r5 = ^^fn; // represents a function +constexpr auto r6 = ^^Enum::A; // represents an enumerator +constexpr auto r7 = ^^Alias; // represents a type alias +constexpr auto r8 = ^^S; // represents a type +constexpr auto r9 = ^^S::mem; // represents a class member +constexpr auto r10 = std::meta::members_of(^^S, ctx)[1]; // represents an unnamed bit-field +constexpr auto r11 = ^^TCls; // represents a class template +constexpr auto r12 = ^^TFn; // represents a function template +constexpr auto r13 = ^^TVar; // represents a variable template +constexpr auto r14 = ^^Concept; // represents a concept +constexpr auto r15 = ^^NSAlias; // represents a namespace alias +constexpr auto r16 = ^^NS; // represents a namespace +constexpr auto r17 = std::meta::bases_of(^^S, ctx)[0]; // represents a direct base class relationship +constexpr auto r18 = + std::meta::data_member_spec(^^int, {.name="member"}); // represents a data member description +\end{codeblock} +\end{example} + +\pnum +\recommended +Implementations should not represent other constructs +specified in this document, such as +\grammarterm{using-declarator}s, +partial template specializations, +attributes, placeholder types, +statements, or +expressions, +as values of type \tcode{std::meta::info}. +\begin{note} +Future revisions of this document can specify semantics for reflections +representing any such constructs. +\end{note} + \pnum \indextext{type!fundamental}% The types described in this subclause @@ -6079,12 +6347,14 @@ \pnum \indextext{value computation|(}% -Reading an object designated by a \keyword{volatile} -glvalue\iref{basic.lval}, modifying an object, calling a library I/O -function, or calling a function that does any of those operations are -all -\defn{side effects}, which are changes in the state of the execution -environment. \defnx{Evaluation}{evaluation} of an expression (or a +Reading an object designated by a \keyword{volatile} glvalue\iref{basic.lval}, +modifying an object, +producing an injected declaration\iref{expr.const}, +calling a library I/O function, or +calling a function that does any of those operations +are all \defn{side effects}, +which are changes in the state of the execution or translation environment. +\defnx{Evaluation}{evaluation} of an expression (or a subexpression) in general includes both value computations (including determining the identity of an object for glvalue evaluation and fetching a value previously assigned to an object for prvalue evaluation) and @@ -6257,6 +6527,14 @@ signal handler is usually unsequenced with respect to the rest of the program. \end{note} +\pnum +During the evaluation of an expression +as a core constant expression\iref{expr.const}, +evaluations of operands of individual operators and +of subexpressions of individual expressions +that are otherwise either unsequenced or indeterminately sequenced +are evaluated in lexical order. + \rSec2[intro.multithread]{Multi-threaded executions and data races} \rSec3[intro.multithread.general]{General} diff --git a/source/classes.tex b/source/classes.tex index f0d9a26229..0b6c2d2671 100644 --- a/source/classes.tex +++ b/source/classes.tex @@ -555,6 +555,7 @@ using-declaration\br using-enum-declaration\br static_assert-declaration\br + consteval-block-declaration\br template-declaration\br explicit-specialization\br deduction-guide\br @@ -646,13 +647,14 @@ \end{note} \pnum -A \grammarterm{member-declaration} does not declare new members of the class +A \grammarterm{member-declaration} does not itself declare new members of the class if it is \begin{itemize} \item a friend declaration\iref{class.friend}, \item a \grammarterm{deduction-guide}\iref{temp.deduct.guide}, \item a \grammarterm{template-declaration} whose \grammarterm{declaration} is one of the above, \item a \grammarterm{static_assert-declaration}, +\item a \grammarterm{consteval-block-declaration}, \item a \grammarterm{using-declaration}\iref{namespace.udecl}, or \item an \grammarterm{empty-declaration}. \end{itemize} @@ -686,10 +688,21 @@ Any other data member or member function is a \defnadj{non-static}{member} (a \defnadj{non-static}{data member} or \defnadj{non-static}{member function}\iref{class.mfct.non.static}, respectively). -\begin{note} -A non-static data member of non-reference -type is a member subobject of a class object\iref{intro.object}. -\end{note} + +\pnum +Every object of class type has a unique member subobject +corresponding to each of its direct non-static data members. +If any non-static data member of a class \tcode{C} is of reference type, +then let \tcode{D} be an invented class +that is identical to \tcode{C} +except that each non-static member of \tcode{D} corresponding to +a member of \tcode{C} of type ``reference to \tcode{T}'' +instead has type ``pointer to \tcode{T}''. +Every member subobject of a complete object of type \tcode{C} +has the same size, alignment, and offset +as that of the corresponding subobject of a complete object of type \tcode{D}. +The size and alignment of \tcode{C} are the same as +the size and alignment of \tcode{D}. \pnum A member shall not be declared twice in the @@ -999,6 +1012,46 @@ pointer-interconvertible\iref{basic.compound,expr.static.cast}. \end{note} +\pnum +A \defnadj{data member}{description} is +a quintuple ($T$, $N$, $A$, $W$, $\mathit{NUA}$) +describing the potential declaration of a non-static data member where +\begin{itemize} +\item $T$ is a type, +\item $N$ is an identifier or $\bot$, +\item $A$ is an alignment or $\bot$, +\item $W$ is a bit-field width or $\bot$, and +\item $\mathit{NUA}$ is a boolean value. +\end{itemize} +Two data member descriptions are equal +if each of their respective components are the same entities, +are the same identifiers, have equal values, or are both $\bot$. +\begin{note} +The components of a data member description describe a data member such that +\begin{itemize} +\item +its type is specified using the type given by $T$, +\item +it is declared with the name given by $N$ +if $N$ is not $\bot$ and is otherwise unnamed, +\item +it is declared with the \grammarterm{alignment-specifier}\iref{dcl.align} +given by \tcode{alignas($A$)} +if $A$ is not $\bot$ and +is otherwise declared without an \grammarterm{alignment-specifier}, +\item +it is a bit-field\iref{class.bit} with the width given by $W$ +if W is not $\bot$ and is otherwise not a bit-field, and +\item +it is declared with +the attribute \tcode{[[no_unique_address]]}\iref{dcl.attr.nouniqueaddr} +if $\mathit{NUA}$ is true and is otherwise declared without that attribute. +\end{itemize} +Data member descriptions are represented by reflections\iref{basic.fundamental} +returned by \tcode{std::meta::data_member_spec}\iref{meta.reflection.define.aggregate} and +can be reified as data members of a class using \tcode{std::meta::define_aggregate}. +\end{note} + \rSec2[class.mfct]{Member functions}% \indextext{member function!class} @@ -3515,7 +3568,12 @@ The class denoted by the \grammarterm{class-or-decltype} of a \grammarterm{base-specifier} is called a \defnadj{direct}{base class} -for the class being defined. +for the class being defined; +for each such \grammarterm{base-specifier}, +the corresponding \defnadj{direct base class}{relationship} +is the ordered pair (\tcode{D}, \tcode{B}) +where \tcode{D} is the class being defined and +\tcode{B} is the direct base class. \indextext{base class}% \indextext{derivation|see{inheritance}}% The lookup for the component name of @@ -4346,9 +4404,10 @@ \end{codeblock} \end{example} \begin{note} -Because access control applies to the declarations named, if access control is applied to a -\grammarterm{typedef-name}, only the accessibility of the typedef or alias declaration itself is considered. -The accessibility of the entity referred to by the \grammarterm{typedef-name} is not considered. +Because access control applies to the declarations named, +if access control is applied to a type alias, +only the accessibility of the typedef or alias declaration itself is considered. +The accessibility of the underlying entity is not considered. \begin{example} \begin{codeblock} class A { @@ -4739,10 +4798,18 @@ to a pointer to a private or protected immediate base class of \tcode{X}. \end{note} -The access to a member is affected by the class in which the member is -named. -This naming class is -the class in whose scope name lookup performed a search that found the member. +An expression $E$ that designates a member \tcode{m} +has a \defnadj{designating}{class} +that affects the access to \tcode{m}. +This designating class is either +\begin{itemize} +\item +the innermost class of which \tcode{m} is directly a member +if $E$ is a \grammarterm{splice-expression} or +\item +the class in whose scope name lookup performed a search +that found \tcode{m} otherwise. +\end{itemize} \begin{note} This class can be explicit, e.g., when a \grammarterm{qualified-id} @@ -4754,7 +4821,7 @@ \grammarterm{qualified-id} are used to name the member (as in \tcode{p->T::m}), -the class naming the member is the class denoted by the +the class designating the member is the class designated by the \grammarterm{nested-name-specifier} of the \grammarterm{qualified-id} @@ -4765,11 +4832,13 @@ \tcode{m} is accessible at the point \placeholder{R} -when named in class +when designated in class \tcode{N} if \begin{itemize} \item +\tcode{m} is designated by a \grammarterm{splice-expression}, or +\item \tcode{m} as a member of \tcode{N} @@ -4811,7 +4880,7 @@ \tcode{m} is accessible at \placeholder{R} -when named in class +when designated in class \tcode{B}. \begin{example} \begin{codeblock} @@ -4837,10 +4906,10 @@ left operand (considered as a pointer in the ``\tcode{.}'' operator case) cannot be implicitly converted to a -pointer to the naming class of the right operand. +pointer to the designating class of the right operand. \begin{note} This requirement is in addition to the requirement that -the member be accessible as named. +the member be accessible as designated. \end{note} \rSec2[class.friend]{Friends}% diff --git a/source/compatibility.tex b/source/compatibility.tex index 2e4d0d5bb6..24b7184c96 100644 --- a/source/compatibility.tex +++ b/source/compatibility.tex @@ -13,6 +13,22 @@ \rSec2[diff.cpp23.lex]{\ref{lex}: Lexical conventions} +\diffref{lex.operators} +\change +New operator \tcode{\caret\caret}. +\rationale +Required for new features. +\effect +Valid \CppXXIII{} code that contains two consecutive \tcode{\caret} tokens +can be ill-formed in this revision of \Cpp{}. +\begin{example} +\begin{codeblock} +struct C { int operator^(int); }; +int operator^(int (C::*p)(int), C); +int i = &C::operator^^C{}; // ill-formed; previously well-formed +\end{codeblock} +\end{example} + \diffref{lex.key} \change New keywords. @@ -148,6 +164,22 @@ \end{codeblock} \end{example} +\diffref{dcl.attr.grammar} +\change +New token \tcode{:]}. +\rationale +Required for new features. +\effect +Valid \CppXXIII{} code that contained an \grammarterm{attribute-specifier} +with an \grammarterm{attribute-using-prefix} +but no attributes and no whitespace is ill-formed in this revision of \Cpp{}. +\begin{example} +\begin{codeblock} +struct [[using CC:]] C; // ill-formed; previously well-formed +struct [[using DD: ]] D; // OK +\end{codeblock} +\end{example} + \rSec2[diff.cpp23.temp]{\ref{temp}: templates} \diffref{temp.constr} diff --git a/source/declarations.tex b/source/declarations.tex index 2e575bbbba..7c2a79be37 100644 --- a/source/declarations.tex +++ b/source/declarations.tex @@ -53,6 +53,7 @@ using-enum-declaration\br using-directive\br static_assert-declaration\br + consteval-block-declaration\br alias-declaration\br opaque-enum-declaration \end{bnf} @@ -102,6 +103,11 @@ \keyword{static_assert} \terminal{(} constant-expression \terminal{,} static_assert-message \terminal{)} \terminal{;} \end{bnf} +\begin{bnf} +\nontermdef{consteval-block-declaration}\br + \keyword{consteval} compound-statement +\end{bnf} + \begin{bnf} \nontermdef{empty-declaration}\br \terminal{;} @@ -245,8 +251,7 @@ If the \grammarterm{decl-specifier-seq} contains the \keyword{typedef} specifier, the declaration is a \defnx{typedef declaration}{declaration!typedef} and each \grammarterm{declarator-id} -is declared to be a \grammarterm{typedef-name}, synonymous with its -associated type\iref{dcl.typedef}. +is declared to be a \grammarterm{typedef-name}\iref{dcl.typedef}. \begin{note} Such a \grammarterm{declarator-id} is an \grammarterm{identifier}\iref{class.conv.fct}. @@ -382,6 +387,35 @@ \end{codeblock} \end{example} +\pnum +For a \grammarterm{consteval-block-declaration} $D$, +the expression $E$ corresponding to $D$ is: +\begin{codeblock} + [] -> void static consteval @\grammarterm{compound-statement}@ () +\end{codeblock} +$E$ shall be a constant expression\iref{expr.const}. +\begin{note} +The evaluation of the expression +corresponding to a \grammarterm{consteval-block-declaration}\iref{lex.phases} +can produce injected declarations as side effects. +\end{note} +\begin{example} +\begin{codeblock} +struct S; +consteval { + std::meta::define_aggregate(^^S, {}); // OK + + template + struct X { }; // error: local templates are not allowed + + template + concept C = true; // error: local concepts are not allowed + + return; // OK +} +\end{codeblock} +\end{example} + \pnum An \grammarterm{empty-declaration} has no effect. @@ -708,9 +742,8 @@ \pnum Declarations containing the \grammarterm{decl-specifier} \keyword{typedef} -declare identifiers that can be used later for naming -fundamental\iref{basic.fundamental} or compound\iref{basic.compound} -types. The \keyword{typedef} specifier shall not be +declare \defnadjx{type}{aliases}{alias}. +The \keyword{typedef} specifier shall not be combined in a \grammarterm{decl-specifier-seq} with any other kind of specifier except a \grammarterm{defining-type-specifier}, and it shall not be used in the \grammarterm{decl-specifier-seq} of a @@ -728,14 +761,12 @@ A name declared with the \keyword{typedef} specifier becomes a \grammarterm{typedef-name}. -A \grammarterm{typedef-name} names +The underlying entity of the type alias is the type associated with the \grammarterm{identifier}\iref{dcl.decl} or \grammarterm{simple-template-id}\iref{temp.pre}; \indextext{declaration!typedef@\tcode{typedef} as type}% \indextext{equivalence!type}% -\indextext{synonym!type name as}% -a \grammarterm{typedef-name} is thus a synonym for another type. A -\grammarterm{typedef-name} does not introduce a new type the way a class +A \grammarterm{typedef-name} does not introduce a new type the way a class declaration\iref{class.name} or enum declaration\iref{dcl.enum} does. \begin{example} After @@ -752,14 +783,14 @@ \end{example} \pnum -A \grammarterm{typedef-name} can also be introduced by an +A type alias can also be declared by an \grammarterm{alias-declaration}. The \grammarterm{identifier} following the -\tcode{using} keyword is not looked up; it becomes a \grammarterm{typedef-name} +\tcode{using} keyword is not looked up; +it becomes the \grammarterm{typedef-name} of a type alias and the optional \grammarterm{attribute-specifier-seq} following the -\grammarterm{identifier} appertains to that \grammarterm{typedef-name}. -Such a \grammarterm{typedef-name} has the same -semantics as if it were introduced by the \keyword{typedef} specifier. In -particular, it does not define a new type. +\grammarterm{identifier} appertains to that type alias. +Such a type alias has the same +semantics as if it were introduced by the \keyword{typedef} specifier. \begin{example} \begin{codeblock} using handler_t = void (*)(int); @@ -1377,7 +1408,8 @@ \begin{bnf} \nontermdef{computed-type-specifier}\br decltype-specifier\br - pack-index-specifier + pack-index-specifier\br + splice-type-specifier \end{bnf} \pnum @@ -1412,12 +1444,21 @@ is a placeholder for a type to be deduced\iref{dcl.spec.auto}. \indextext{deduction!class template arguments}% -A \grammarterm{type-specifier} of the form -\opt{\keyword{typename}} \opt{\grammarterm{nested-name-specifier}} \grammarterm{template-name} -is a placeholder for -a deduced class type\iref{dcl.type.class.deduct}. -The \grammarterm{nested-name-specifier}, if any, shall be non-dependent and -the \grammarterm{template-name} shall name a deducible template. +A \grammarterm{type-specifier} is a placeholder for +a deduced class type\iref{dcl.type.class.deduct} if either +\begin{itemize} +\item +it is of the form +\opt{\keyword{typename}} \opt{\grammarterm{nested-name-specifier}} \grammarterm{template-name} or +\item +it is of the form \opt{\keyword{typename}} \grammarterm{splice-specifier} and +the \grammarterm{splice-specifier} designates +a class template or alias template. +\end{itemize} +The \grammarterm{nested-name-specifier} or \grammarterm{splice-specifier}, +if any, shall be non-dependent and +the \grammarterm{template-name} or \grammarterm{splice-specifier} +shall designate a deducible template. A \defnadj{deducible}{template} is either a class template or is an alias template whose \grammarterm{defining-type-id} is of the form @@ -1455,6 +1496,7 @@ \grammarterm{placeholder-type-specifier} & the type as defined in~\ref{dcl.spec.auto}\\ \grammarterm{template-name} & the type as defined in~\ref{dcl.type.class.deduct}\\ +\grammarterm{splice-type-specifier} & the type as defined in~\ref{dcl.type.splice}\\ \tcode{char} & ``\tcode{char}'' \\ \tcode{unsigned char} & ``\tcode{unsigned char}'' \\ \tcode{signed char} & ``\tcode{signed char}'' \\ @@ -1683,6 +1725,10 @@ type of the entity named by $E$. If there is no such entity, the program is ill-formed; +\item otherwise, if $E$ is an unparenthesized \grammarterm{splice-expression}, +\tcode{decltype($E$)} is the type of the entity, object, or value +designated by the \grammarterm{splice-specifier} of $E$; + \item otherwise, if $E$ is an xvalue, \tcode{decltype($E$)} is \tcode{T\&\&}, where \tcode{T} is the type of $E$; @@ -1706,11 +1752,13 @@ decltype(i) x2; // type is \tcode{int} decltype(a->x) x3; // type is \tcode{double} decltype((a->x)) x4 = x3; // type is \tcode{const double\&} +decltype([:^^x1:]) x5 = 18; // type is \tcode{const int\&\&} +decltype(([:^^x1:])) x6 = 19; // type is \tcode{const int\&} void f() { [](auto ...pack) { - decltype(pack...[0]) x5; // type is \tcode{int} - decltype((pack...[0])) x6; // type is \tcode{int\&} + decltype(pack...[0]) x7; // type is \tcode{int} + decltype((pack...[0])) x8; // type is \tcode{int\&} }(0); } \end{codeblock} @@ -2266,6 +2314,59 @@ container e{5, 6}; // error: \tcode{int} is not an iterator \end{codeblock} \end{example} + +\rSec3[dcl.type.splice]{Type splicing} + +\begin{bnf} +\nontermdef{splice-type-specifier}\br + \opt{\keyword{typename}} splice-specifier\br + \opt{\keyword{typename}} splice-specialization-specifier +\end{bnf} + +\pnum +A \grammarterm{splice-specifier} or +\grammarterm{splice-specialization-specifier} +immediately followed by \tcode{::} +is never interpreted as part of a \grammarterm{splice-type-specifier}. +A \grammarterm{splice-specifier} or +\grammarterm{splice-specialization-specifier} +not preceded by \keyword{typename} +is only interpreted as a \grammarterm{splice-type-specifier} +within a type-only context\iref{temp.res.general}. +\begin{example} +\begin{codeblock} +template void tfn() { + typename [:R:]::type m; // OK, \keyword{typename} applies to the qualified name +} + +struct S { using type = int; }; +void fn() { + [:^^S::type:] *var; // error: \tcode{[:\caret\caret S::type:]} is an expression + typename [:^^S::type:] *var; // OK, declares variable with type \tcode{int*} +} + +using alias = [:^^S::type:]; // OK, type-only context +\end{codeblock} +\end{example} + +\pnum +For a \grammarterm{splice-type-specifier} of the form +\opt{\keyword{typename}} \grammarterm{splice-specifier}, +the \grammarterm{splice-specifier} shall designate +a type, a class template, or an alias template. +The \grammarterm{splice-type-specifier} designates +the same entity as the \grammarterm{splice-specifier}. + +\pnum +For a \grammarterm{splice-type-specifier} of the form +\opt{\keyword{typename}} \grammarterm{splice-specialization-specifier}, +the \grammarterm{splice-specifier} of +the \grammarterm{splice-specialization-specifier} +shall designate a template \tcode{T} +that is either a class template or an alias template. +The \grammarterm{splice-type-specifier} designates +the specialization of \tcode{T} corresponding to +the template argument list of the \grammarterm{splice-specialization-specifier}. \indextext{specifier|)}% \rSec1[dcl.decl]{Declarators}% @@ -3276,7 +3377,7 @@ \end{ncsimplebnf} and the \grammarterm{nested-name-specifier} -denotes a class, +designates a class, and the type of the contained \grammarterm{declarator-id} in the declaration \tcode{T} \tcode{D1} @@ -3289,6 +3390,7 @@ \tcode{T}''. The optional \grammarterm{attribute-specifier-seq}\iref{dcl.attr.grammar} appertains to the pointer-to-member. +The \grammarterm{nested-name-specifier} shall not designate an anonymous union. \pnum \begin{example} @@ -3469,8 +3571,10 @@ and the type of the array is ``array of \tcode{N} \tcode{U}''. \pnum -Furthermore, if there is a reachable declaration of the entity that inhabits the same -scope in which the bound was specified, an omitted array bound is taken to +Furthermore, if there is a reachable declaration of the entity +that specifies a bound and +has the same host scope\iref{basic.scope.scope}, +an omitted array bound is taken to be the same as in that earlier declaration, and similarly for the definition of a static data member of a class. \begin{example} @@ -3487,6 +3591,9 @@ extern int x[]; int i = sizeof(x); // error: incomplete object type } + +namespace A { extern int z[3]; } +int A::z[] = {}; // OK, defines an array of 3 elements \end{codeblock} \end{example} @@ -3839,7 +3946,7 @@ \pnum A function type with a \grammarterm{cv-qualifier-seq} or a -\grammarterm{ref-qualifier} (including a type named by +\grammarterm{ref-qualifier} (including a type denoted by \grammarterm{typedef-name}\iref{dcl.typedef,temp.param}) shall appear only as: \begin{itemize} @@ -3855,15 +3962,18 @@ \item the \grammarterm{type-id} of a \grammarterm{template-argument} for a \grammarterm{type-parameter}\iref{temp.arg.type}. + +\item the operand of a \grammarterm{reflect-expression}\iref{expr.reflect}. \end{itemize} \begin{example} \begin{codeblock} typedef int FIC(int) const; -FIC f; // error: does not declare a member function +FIC f; // error: does not declare a member function struct S { - FIC f; // OK + FIC f; // OK }; -FIC S::*pm = &S::f; // OK +FIC S::*pm = &S::f; // OK +constexpr std::meta::info yeti = ^^void(int) const &; // OK \end{codeblock} \end{example} @@ -4220,9 +4330,9 @@ \pnum For non-template functions, default arguments can be added in later declarations of a -function that inhabit the same scope. -Declarations that inhabit different -scopes have completely distinct sets of default arguments. +function that have the same host scope. +Declarations that have different +host scopes have completely distinct sets of default arguments. That is, declarations in inner scopes do not acquire default arguments from declarations in outer scopes, and vice versa. @@ -4393,9 +4503,19 @@ int h(int a, int b = sizeof(a)); // OK, unevaluated operand\iref{term.unevaluated.operand} \end{codeblock} \end{example} -A non-static member shall not appear in a default argument unless it appears as -the \grammarterm{id-expression} of a class member access expression\iref{expr.ref} or -unless it is used to form a pointer to member\iref{expr.unary.op}. +A non-static member shall not be designated in a default argument unless +\begin{itemize} +\item +it is designated by +the \grammarterm{id-expression} or \grammarterm{splice-expression} +of a class member access expression\iref{expr.ref}, +\item +it is designated by an expression +used to form a pointer to member\iref{expr.unary.op}, or +\item +it appears as the operand of +a \grammarterm{reflect-expression}\iref{expr.reflect}. +\end{itemize} \begin{example} The declaration of \tcode{X::mem1()} @@ -4407,8 +4527,10 @@ int b; class X { int a; - int mem1(int i = a); // error: non-static member \tcode{a} used as default argument - int mem2(int i = b); // OK; use \tcode{X::b} + int mem1(int i = a); // error: non-static member \tcode{a} used as default argument + int mem2(int i = b); // OK, use \tcode{X::b} + consteval void mem3(std::meta::info r = ^^a) {} // OK + int mem4(int i = [:^^a:]); // error: non-static member a designated in default argument static int b; }; \end{codeblock} @@ -4433,10 +4555,13 @@ int (*p2)() = &f; // error: type mismatch \end{codeblock} \end{example} +\begin{note} When an overload set contains a declaration of a function -that inhabits a scope $S$, -any default argument associated with any reachable declaration that inhabits $S$ -is available to the call. +whose host scope is $S$, +any default argument associated with any reachable declaration +whose host scope is $S$ +is available to the call\iref{over.match.viable}. +\end{note} \begin{note} The candidate might have been found through a \grammarterm{using-declarator} from which the declaration that provides the default argument is not reachable. @@ -4895,20 +5020,16 @@ \indextext{initialization!default}% \indextext{variable!indeterminate uninitialized}% \indextext{initialization!zero-initialization}% -To -\defnx{zero-initialize}{zero-initialization} -an object or reference of type -\tcode{T} -means: +To \defnx{zero-initialize}{zero-initialization} +an object or reference of type \tcode{T} means: \begin{itemize} \item -if -\tcode{T} -is a scalar type\iref{term.scalar.type}, the -object -is initialized to the value obtained by converting the integer literal \tcode{0} -(zero) to -\tcode{T}; +if \tcode{T} is \tcode{std::meta::info}, +the object is initialized to a null reflection value; +\item +if \tcode{T} is any other scalar type\iref{term.scalar.type}, +the object is initialized to the value +obtained by converting the integer literal \tcode{0} (zero) to \tcode{T}; \begin{footnote} As specified in~\ref{conv.ptr}, converting an integer literal whose value is @@ -4974,6 +5095,9 @@ shall be met and each element is default-initialized. +\item +If \tcode{T} is \tcode{std::meta::info}, the object is zero-initialized. + \item Otherwise, no initialization is performed. @@ -5002,8 +5126,9 @@ \end{itemize} If a program calls for the default-initialization of an object of a -const-qualified type \tcode{T}, -\tcode{T} shall be a const-default-constructible class type or array thereof. +const-qualified type \tcode{T}, \tcode{T} shall be +\tcode{std::meta::\linebreak info} or a const-default-constructible class type or +array thereof. \pnum To @@ -7002,8 +7127,10 @@ deleted definition or a function that is implicitly defined as deleted. \pnum -A program that refers to a deleted function implicitly or explicitly, other -than to declare it, is ill-formed. +A construct that designates a deleted function implicitly or explicitly, +other than to declare it or to appear as the operand of +a \grammarterm{reflect-expression}\iref{expr.reflect}, +is ill-formed. \recommended The resulting diagnostic message should include @@ -7992,11 +8119,15 @@ \begin{bnf} \nontermdef{using-enum-declarator}\br \opt{nested-name-specifier} identifier\br - \opt{nested-name-specifier} simple-template-id + \opt{nested-name-specifier} simple-template-id\br + splice-type-specifier \end{bnf} \pnum -A \grammarterm{using-enum-declarator} +A \grammarterm{using-enum-declarator} of +the form \grammarterm{splice-type-specifier} +designates the same type designated by the \grammarterm{splice-type-specifier}. +Any other \grammarterm{using-enum-declarator} names the set of declarations found by type-only lookup\iref{basic.lookup.general} for the \grammarterm{using-enum-declarator}\iref{basic.lookup.unqual,basic.lookup.qual}. @@ -8260,7 +8391,7 @@ \grammarterm{unnamed-namespace-definition} and all occurrences of \exposid{unique} in a translation unit are replaced by the same identifier, and this identifier differs from all other -identifiers in the translation unit. +identifiers in the program. The optional \grammarterm{attribute-specifier-seq} in the \grammarterm{unnamed-namespace-definition} appertains to \exposid{unique}. @@ -8292,8 +8423,8 @@ \indextext{synonym} \pnum -A \grammarterm{namespace-alias-definition} declares an alternate name for a -namespace according to the following grammar: +A \grammarterm{namespace-alias-definition} declares a \defnadj{namespace}{alias} +according to the following grammar: \begin{bnf} \nontermdef{namespace-alias}\br @@ -8302,7 +8433,8 @@ \begin{bnf} \nontermdef{namespace-alias-definition}\br - \keyword{namespace} identifier \terminal{=} qualified-namespace-specifier \terminal{;} + \keyword{namespace} identifier \terminal{=} qualified-namespace-specifier \terminal{;}\br + \keyword{namespace} identifier \terminal{=} splice-specifier \terminal{;}\br \end{bnf} \begin{bnf} @@ -8310,10 +8442,19 @@ \opt{nested-name-specifier} namespace-name \end{bnf} +\pnum +The \grammarterm{splice-specifier} (if any) +shall designate a namespace that is not the global namespace. + \pnum The \grammarterm{identifier} in a \grammarterm{namespace-alias-definition} -becomes a \grammarterm{namespace-alias} and denotes the namespace denoted by the -\grammarterm{qualified-namespace-specifier}. +becomes a \grammarterm{namespace-alias}. + +\pnum +The underlying entity\iref{basic.pre} of the namespace alias is +the namespace either +denoted by the \grammarterm{qualified-namespace-specifier} or +designated by the \grammarterm{splice-specifier}. \begin{note} When looking up a \grammarterm{namespace-name} in a \grammarterm{namespace-alias-definition}, only namespace names are @@ -8325,9 +8466,18 @@ \begin{bnf} \nontermdef{using-directive}\br - \opt{attribute-specifier-seq} \keyword{using} \keyword{namespace} \opt{nested-name-specifier} namespace-name \terminal{;} + \opt{attribute-specifier-seq} \keyword{using} \keyword{namespace} \opt{nested-name-specifier} namespace-name \terminal{;}\br + \opt{attribute-specifier-seq} \keyword{using} \keyword{namespace} splice-specifier \terminal{;} \end{bnf} +\pnum +The \grammarterm{splice-specifier} (if any) shall designate a namespace +that is not the global namespace. +The \grammarterm{nested-name-specifier}, +\grammarterm{namespace-name}, and +\grammarterm{splice-specifier} +shall not be dependent. + \pnum A \grammarterm{using-directive} shall not appear in class scope, but may appear in namespace scope or in block scope. @@ -8340,13 +8490,13 @@ \pnum \begin{note} -A \grammarterm{using-directive} makes the names in the nominated +A \grammarterm{using-directive} makes the names in the designated namespace usable in the scope in which the \grammarterm{using-directive} appears after the \grammarterm{using-directive}\iref{basic.lookup.unqual,namespace.qual}. During unqualified name lookup, the names appear as if they were declared in the nearest enclosing namespace which -contains both the \grammarterm{using-directive} and the nominated +contains both the \grammarterm{using-directive} and the designated namespace. \end{note} @@ -8387,8 +8537,8 @@ \pnum \begin{note} A \grammarterm{using-directive} is transitive: if a scope contains a -\grammarterm{using-directive} that nominates a namespace that itself -contains \grammarterm{using-directive}{s}, the namespaces nominated by those +\grammarterm{using-directive} that designates a namespace that itself +contains \grammarterm{using-directive}{s}, the namespaces designated by those \grammarterm{using-directive}{s} are also eligible to be considered. \end{note} \begin{example} @@ -9279,7 +9429,8 @@ \terminal{(} \opt{balanced-token-seq} \terminal{)}\br \terminal{[} \opt{balanced-token-seq} \terminal{]}\br \terminal{\{} \opt{balanced-token-seq} \terminal{\}}\br - \textnormal{any \grammarterm{token} other than a parenthesis, a bracket, or a brace} + \terminal{[:} \opt{balanced-token-seq} \terminal{:]}\br + \textnormal{any \grammarterm{token} other than \terminal{(}, \terminal{)}, \terminal{[}, \terminal{]}, \terminal{\{}, \terminal{\}}, \terminal{[:}, or \terminal{:]}} \end{bnf} \pnum @@ -9318,7 +9469,9 @@ In an \grammarterm{attribute-list}, an ellipsis may appear only if that \grammarterm{attribute}'s specification permits it. An \grammarterm{attribute} followed by an ellipsis is a pack expansion\iref{temp.variadic}. -An \grammarterm{attribute-specifier} that contains no \grammarterm{attribute}{s} has no +An \grammarterm{attribute-specifier} +that contains no \grammarterm{attribute}{s} and no \grammarterm{alignment-specifier} +has no effect. The order in which the \grammarterm{attribute-token}{s} appear in an \grammarterm{attribute-list} is not significant. If a keyword\iref{lex.key} @@ -9574,7 +9727,7 @@ \pnum The attribute may be applied to the declaration of a class, -a \grammarterm{typedef-name}, +a type alias, a variable, a non-static data member, a function, @@ -9792,7 +9945,7 @@ \pnum The attribute may be applied to the declaration of a class, -\grammarterm{typedef-name}, +type alias, variable (including a structured binding declaration), structured binding, result binding\iref{dcl.contract.res}, diff --git a/source/expressions.tex b/source/expressions.tex index ebc2646472..feecabe0b7 100644 --- a/source/expressions.tex +++ b/source/expressions.tex @@ -147,7 +147,7 @@ \end{importgraphic} \begin{itemize} -\item A \defn{glvalue} is an expression whose evaluation determines the identity of an object or function. +\item A \defn{glvalue} is an expression whose evaluation determines the identity of an object, function, or non-static data member. \item A \defn{prvalue} is an expression whose evaluation initializes an object or computes the value of an operand of an operator, as specified by the context in which it appears, @@ -186,7 +186,8 @@ \begin{note} An expression is an xvalue if it is: \begin{itemize} -\item a move-eligible \grammarterm{id-expression}\iref{expr.prim.id.unqual}, +\item a move-eligible \grammarterm{id-expression}\iref{expr.prim.id.unqual} +or \grammarterm{splice-expression}\iref{expr.prim.splice}, \item the result of calling a function, whether implicitly or explicitly, whose return type is an rvalue reference to object type\iref{expr.call}, @@ -442,6 +443,7 @@ expr.typeid, expr.sizeof, expr.unary.noexcept, +expr.reflect, dcl.type.decltype, temp.pre, temp.concept}. @@ -467,6 +469,7 @@ \item \tcode{(} \grammarterm{expression} \tcode{)}, where \grammarterm{expression} is one of these expressions, \item \grammarterm{id-expression}\iref{expr.prim.id}, +\item \grammarterm{splice-expression}\iref{expr.prim.splice}, \item subscripting\iref{expr.sub}, \item class member access\iref{expr.ref}, \item indirection\iref{expr.unary.op}, @@ -1247,7 +1250,8 @@ id-expression\br lambda-expression\br fold-expression\br - requires-expression + requires-expression\br + splice-expression \end{bnf} \rSec2[expr.prim.literal]{Literals} @@ -1393,6 +1397,9 @@ $E$ is not the \grammarterm{id-expression} of a class member access expression\iref{expr.ref}, and \item +$E$ is not the \grammarterm{id-expression} of +a \grammarterm{reflect-expression}\iref{expr.reflect}, and +\item if $E$ is a \grammarterm{qualified-id}, $E$ is not the un-parenthesized operand of the unary \tcode{\&} operator\iref{expr.unary.op}, @@ -1450,7 +1457,8 @@ \end{itemize} \pnum -An \grammarterm{id-expression} that denotes a non-static data member or +An \grammarterm{id-expression} or \grammarterm{splice-expression} +that designates a non-static data member or implicit object member function of a class can only be used: \begin{itemize} \item as part of a class member access @@ -1463,7 +1471,8 @@ \item to form a pointer to member\iref{expr.unary.op}, or -\item if that \grammarterm{id-expression} denotes a non-static data member +\item if that \grammarterm{id-expression} or \grammarterm{splice-expression} +designates a non-static data member and it appears in an unevaluated operand. \begin{example} \begin{codeblock} @@ -1472,6 +1481,7 @@ }; int i = sizeof(S::m); // OK int j = sizeof(S::m + 42); // OK +int S::*k = &[:^^S::m:]; // OK \end{codeblock} \end{example} \end{itemize} @@ -1779,10 +1789,12 @@ a variable with automatic storage duration that is either a non-volatile object or an rvalue reference to a non-volatile object type. -An \grammarterm{id-expression} is \defn{move-eligible} if +An \grammarterm{id-expression} or +\grammarterm{splice-expression}\iref{expr.prim.splice} +is \defn{move-eligible} if \begin{itemize} \item -it names an implicitly movable entity, +it designates an implicitly movable entity, \item it is the (possibly parenthesized) operand of a \tcode{return}\iref{stmt.return} or @@ -1791,7 +1803,7 @@ \item each intervening scope between the declaration of the entity and -the innermost enclosing scope of the \grammarterm{id-expression} +the innermost enclosing scope of the expression is a block scope and, for a \grammarterm{throw-expression}, is not the block scope of @@ -1817,9 +1829,15 @@ type-name \terminal{::}\br namespace-name \terminal{::}\br computed-type-specifier \terminal{::}\br + splice-scope-specifier \terminal{::}\br nested-name-specifier identifier \terminal{::}\br nested-name-specifier \opt{\keyword{template}} simple-template-id \terminal{::} \end{bnf} +\begin{bnf} +\nontermdef{splice-scope-specifier}\br + splice-specifier\br + \opt{\keyword{template}} splice-specialization-specifier +\end{bnf} \pnum \indextext{component name}% @@ -1832,6 +1850,33 @@ \grammarterm{simple-template-id}, and/or \grammarterm{nested-name-specifier}. +\pnum +A \grammarterm{splice-specifier} or +\grammarterm{splice-specialization-specifier} +that is not followed by \tcode{::} +is never interpreted as part of a \grammarterm{splice-scope-specifier}. +The keyword \keyword{template} may only be omitted +from the form +\tcode{\opt{\keyword{template}} \grammarterm{splice-specialization-specifier} ::} +when the \grammarterm{splice-specialization-specifier} +is preceded by \keyword{typename}. +\begin{example} +\begin{codeblock} +template +struct TCls { + static constexpr int s = V; + using type = int; +}; + +int v1 = [:^^TCls<1>:]::s; +int v2 = template [:^^TCls:]<2>::s; // OK, \keyword{template} binds to \grammarterm{splice-scope-specifier} +typename [:^^TCls:]<3>::type v3 = 3; // OK, \keyword{typename} binds to the qualified name +template [:^^TCls:]<3>::type v4 = 4; // OK, \keyword{template} binds to the \grammarterm{splice-scope-specifier} +typename template [:^^TCls:]<3>::type v5 = 5; // OK, same as \tcode{v3} +[:^^TCls:]<3>::type v6 = 6; // error: unexpected \tcode{<} +\end{codeblock} +\end{example} + \pnum A \grammarterm{nested-name-specifier} is \defn{declarative} if it is part of \begin{itemize} @@ -1846,17 +1891,44 @@ a declarative \grammarterm{nested-name-specifier}. \end{itemize} A declarative \grammarterm{nested-name-specifier} -shall not have a \grammarterm{computed-type-specifier}. +shall not have a \grammarterm{computed-type-specifier} or +a \grammarterm{splice-scope-specifier}. A declaration that uses a declarative \grammarterm{nested-name-specifier} shall be a friend declaration or inhabit a scope that contains the entity being redeclared or specialized. \pnum -The \grammarterm{nested-name-specifier} \tcode{::} nominates +The entity designated by a \grammarterm{nested-name-specifier} +is determined as follows: +\begin{itemize} +\item +The \grammarterm{nested-name-specifier} \tcode{::} designates the global namespace. +\item A \grammarterm{nested-name-specifier} with a \grammarterm{computed-type-specifier} -nominates the type denoted by the \grammarterm{computed-type-specifier}, +designates the same type designated by the \grammarterm{computed-type-specifier}, which shall be a class or enumeration type. +\item +For a \grammarterm{nested-name-specifier} of +the form \tcode{\grammarterm{splice-specifier} ::}, +the \grammarterm{splice-specifier} shall designate +a class or enumeration type or a namespace. +The \grammarterm{nested-name-specifier} designates the same entity +as the \grammarterm{splice-specifier}. +\item +For a \grammarterm{nested-name-specifier} of +the form +\tcode{\opt{\keyword{template}} \grammarterm{splice-specialization-specifier} ::}, +the \grammarterm{splice-specifier} of +the \grammarterm{splice-specialization-specifier} shall designate +a class template or an alias template $T$. +Letting $S$ be the specialization of $T$ +corresponding to the template argument list of +the \grammarterm{splice-specialization-specifier}, +$S$ shall either be a class template specialization or +an alias template specialization that denotes a class or enumeration type. +The \grammarterm{nested-name-specifier} designates the underlying entity of $S$. +\item If a \grammarterm{nested-name-specifier} $N$ is declarative and has a \grammarterm{simple-template-id} with a template argument list $A$ @@ -1867,22 +1939,24 @@ \item If $A$ is the template argument list\iref{temp.arg} of the corresponding \grammarterm{template-head} $H$\iref{temp.mem}, -$N$ nominates the primary template of $T$; +$N$ designates the primary template of $T$; $H$ shall be equivalent to the \grammarterm{template-head} of $T$\iref{temp.over.link}. \item -Otherwise, $N$ nominates the partial specialization\iref{temp.spec.partial} of $T$ +Otherwise, $N$ designates the partial specialization\iref{temp.spec.partial} of $T$ whose template argument list is equivalent to $A$\iref{temp.over.link}; the program is ill-formed if no such partial specialization exists. \end{itemize} -Any other \grammarterm{nested-name-specifier} nominates -the entity denoted by its +\item +Any other \grammarterm{nested-name-specifier} designates +the entity denotes by its \grammarterm{type-name}, \grammarterm{namespace-name}, \grammarterm{identifier}, or \grammarterm{simple-template-id}. If the \grammarterm{nested-name-specifier} is not declarative, the entity shall not be a template. +\end{itemize} \pnum A \grammarterm{qualified-id} shall not be of the form @@ -2137,6 +2211,10 @@ called the \defn{closure type}, whose properties are described below. +\pnum +The closure type is not complete +until the end of its corresponding \grammarterm{compound-statement}. + \pnum The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding @@ -2176,6 +2254,8 @@ respectively, and whose \grammarterm{template-parameter-list} consists of the specified \grammarterm{template-parameter-list}, if any. +The function call operator or the function call operator template are +direct members of the closure type. The \grammarterm{requires-clause} of the function call operator template is the \grammarterm{requires-clause} immediately following \tcode{<}~\grammarterm{template-parameter-list}{}~\tcode{>}, if any. @@ -2528,7 +2608,9 @@ }; \end{codeblock} \end{example} -Further, a variable \mname{func} is implicitly defined at the beginning of +Unless the \grammarterm{compound-statement} is +that of a \grammarterm{consteval-block-declaration}\iref{dcl.pre}, +a variable \mname{func} is implicitly defined at the beginning of the \grammarterm{compound-statement} of the \grammarterm{lambda-expression}, with semantics as described in~\ref{dcl.fct.def.general}. @@ -3275,13 +3357,16 @@ \begin{bnf} \nontermdef{type-requirement}\br - \keyword{typename} \opt{nested-name-specifier} type-name \terminal{;} + \keyword{typename} \opt{nested-name-specifier} type-name \terminal{;}\br + \keyword{typename} splice-specifier\br + \keyword{typename} splice-specialization-specifier \end{bnf} \pnum A \grammarterm{type-requirement} asserts the validity of a type. The component names of a \grammarterm{type-requirement} are those of its -\grammarterm{nested-name-specifier} (if any) and \grammarterm{type-name}. +\grammarterm{nested-name-specifier} (if any) and +\grammarterm{type-name} (if any). \begin{note} The enclosing \grammarterm{requires-expression} will evaluate to \keyword{false} if substitution of template arguments fails. @@ -3292,10 +3377,12 @@ template using Ref = T&; template concept C = requires { - typename T::inner; // required nested member name - typename S; // required valid\iref{temp.names} \grammarterm{template-id}; - // fails if \tcode{T::type} does not exist as a type to which \tcode{0} can be implicitly converted - typename Ref; // required alias template substitution, fails if \tcode{T} is void + typename T::inner; // required nested member name + typename S; // required valid\iref{temp.names} \grammarterm{template-id}; fails if \tcode{T::type} does not exist as a type + // to which \tcode{0} can be implicitly converted + typename Ref; // required alias template substitution, fails if \tcode{T} is void + typename [:T::r1:]; // fails if \tcode{T::r1} is not a reflection of a type + typename [:T::r2:]; // fails if \tcode{T::r2} is not a reflection of a template \tcode{Z} for which \tcode{Z} is a type }; \end{codeblock} \end{example} @@ -3430,6 +3517,150 @@ \indextext{expression!requires|)} \indextext{expression!primary|)} +\rSec2[expr.prim.splice]{Expression splicing} + +\begin{bnf} +\nontermdef{splice-expression}\br + splice-specifier\br + \keyword{template} splice-specifier\br + \keyword{template} splice-specialization-specifier +\end{bnf} + +\pnum +A +\grammarterm{splice-specifier} or \grammarterm{splice-specialization-specifier} +immediately followed by \tcode{::} or preceded by \keyword{typename} +is never interpreted as part of a \grammarterm{splice-expression}. +\begin{example} +\begin{codeblock} +struct S { static constexpr int a = 1; }; +template struct TCls { static constexpr int b = 2; }; + +constexpr int c = [:^^S:]::a; // OK, \tcode{[:\caret\caret S:]} is not an expression +constexpr int d = template [:^^TCls:]::b; // OK, \tcode{template [:\caret\caret TCls:]} is not an expression +template constexpr int e = [:V:]; // OK +constexpr int f = template [:^^e:]<^^S::a>; // OK + +constexpr auto g = typename [:^^int:](42); // OK, \tcode{typename [:\caret\caret int:]} is a \grammarterm{splice-type-specifier} + +constexpr auto h = ^^g; +constexpr auto i = e<[:^^h:]>; // error: unparenthesized \grammarterm{splice-expression} used as template argument +constexpr auto j = e<([:^^h:])>; // OK +\end{codeblock} +\end{example} + +\pnum +For a \grammarterm{splice-expression} of the form \grammarterm{splice-specifier}, +let $S$ be the construct designated by \grammarterm{splice-specifier}. +\begin{itemize} +\item +The expression is ill-formed if $S$ is +\begin{itemize} +\item +a constructor, +\item +a destructor, +\item +an unnamed bit-field, or +\item +a local entity\iref{basic.pre} such that +\begin{itemize} +\item +there is a lambda scope that intervenes +between the expression and the point at which $S$ was introduced and +\item +the expression would be potentially evaluated +if the effect of any enclosing \keyword{typeid} expressions\iref{expr.typeid} +were ignored. +\end{itemize} +\end{itemize} +\item +Otherwise, if $S$ is a function $F$, +the expression denotes an overload set containing all declarations of $F$ +that precede either the expression or +the point immediately following the \grammarterm{class-specifier} of +the outermost class for which the expression is in a complete-class context; +overload resolution is performed\iref{over.match,over.over}. +\item +Otherwise, if $S$ is an object or a non-static data member, +the expression is an lvalue designating $S$. +The expression has the same type as that of $S$, and +is a bit-field if and only if $S$ is a bit-field. +\begin{note} +The implicit transformation +whereby an \grammarterm{id-expression} denoting a non-static member +becomes a class member access\iref{expr.prim.id} +does not apply to a \grammarterm{splice-expression}. +\end{note} +\item +Otherwise, if $S$ is a variable or a structured binding, +$S$ shall either have static or thread storage duration or +shall inhabit a scope enclosing the expression. +The expression is an lvalue referring to the object or function $X$ +associated with or referenced by $S$, +has the same type as that of $S$, and +is a bit-field if and only if $X$ is a bit-field. +\begin{note} +The type of a \grammarterm{splice-expression} +designating a variable or structured binding of reference type +will be adjusted to a non-reference type\iref{expr.type}. +\end{note} +\item +Otherwise, if $S$ is a value or an enumerator, +the expression is a prvalue that computes $S$ and +whose type is the same as that of $S$. +\item +Otherwise, the expression is ill-formed. +\end{itemize} + +\pnum +For a \grammarterm{splice-expression} of +the form \tcode{\keyword{template} \grammarterm{splice-specifier}}, +the \grammarterm{splice-specifier} shall designate a function template $T$ +that is not a constructor template. +The expression denotes an overload set containing all declarations of $T$ +that precede either the expression or +the point immediately following the \grammarterm{class-specifier} of +the outermost class for which the expression is in a complete-class context; +overload resolution is performed. +\begin{note} +During overload resolution, +candidate function templates undergo template argument deduction and +the resulting specializations are considered as candidate functions. +\end{note} + +\pnum +For a \grammarterm{splice-expression} of +the form \tcode{template \grammarterm{splice-specialization-specifier}}, +the \grammarterm{splice-specifier} of +the \grammarterm{splice-specialization-specifier} +shall designate a template $T$. +\begin{itemize} +\item +If $T$ is a function template, +the expression denotes an overload set containing all declarations of $T$ +that precede either the expression or +the point immediately following the \grammarterm{class-specifier} of +the outermost class for which the expression is in a complete-class context; +overload resolution is performed\iref{over.match,over.over}. +\item +Otherwise, if $T$ is a variable template, +let $S$ be the specialization of $T$ corresponding to +the template argument list of the \grammarterm{splice-specialization-specifier}. +The expression is an lvalue referring to +the object associated with $S$ and has the same type as that of $S$. +\item +Otherwise, the expression is ill-formed. +\end{itemize} +\begin{note} +Class members are accessible from any point +when designated by \grammarterm{splice-expression}s\iref{class.access.base}. +A class member access expression\iref{expr.ref} +whose right operand is a \grammarterm{splice-expression} is ill-formed +if the left operand (considered as a pointer) cannot be implicitly converted +to a pointer to the designating class of the right operand. +\end{note} + \rSec1[expr.compound]{Compound expressions} \rSec2[expr.post]{Postfix expressions}% @@ -3450,7 +3681,9 @@ simple-type-specifier braced-init-list\br typename-specifier braced-init-list\br postfix-expression \terminal{.} \opt{\terminal{template}} id-expression\br + postfix-expression \terminal{.} splice-expression\br postfix-expression \terminal{->} \opt{\terminal{template}} id-expression\br + postfix-expression \terminal{->} splice-expression\br postfix-expression \terminal{++}\br postfix-expression \terminal{--}\br \keyword{dynamic_cast} \terminal{<} type-id \terminal{>} \terminal{(} expression \terminal{)}\br @@ -3919,10 +4152,12 @@ A postfix expression followed by a dot \tcode{.} or an arrow \tcode{->}, optionally followed by the keyword \keyword{template}, and then followed by an -\grammarterm{id-expression}, is a postfix expression. +\grammarterm{id-expression} or a \grammarterm{splice-expression}, +is a postfix expression. \begin{note} -If the keyword \keyword{template} is used, -the following unqualified name +If the keyword \keyword{template} is used and +followed by an \grammarterm{id-expression}, +the unqualified name is considered to refer to a template\iref{temp.names}. If a \grammarterm{simple-template-id} results and is followed by a \tcode{::}, the \grammarterm{id-expression} is a \grammarterm{qualified-id}. @@ -3930,16 +4165,16 @@ \pnum \indextext{type!incomplete}% -For the first option (dot), -if the \grammarterm{id-expression} names a static member or an enumerator, +For a dot that is followed by an expression +that designates a static member or an enumerator, the first expression is a discarded-value expression\iref{expr.context}; -if the \grammarterm{id-expression} names a non-static data member, +if the expression after the dot designates a non-static data member, the first expression shall be a glvalue. -For the second option (arrow), the first expression +A postfix expression that is followed by an arrow shall be a prvalue having pointer type. The expression \tcode{E1->E2} is converted to the equivalent form \tcode{(*(E1)).E2}; the remainder of -\ref{expr.ref}~will address only the first option (dot). +\ref{expr.ref}~will address only the form using a dot. \begin{footnote} Note that \tcode{(*(E1))} is an lvalue. @@ -3955,12 +4190,14 @@ \grammarterm{id-expression} denotes a static member. \end{footnote} the result of that evaluation, -together with the \grammarterm{id-expression}, +together with +the \grammarterm{id-expression} or \grammarterm{splice-expression}, determines the result of the entire postfix expression. \pnum Abbreviating -\grammarterm{postfix-expression}\tcode{.}\grammarterm{id-expression} +\grammarterm{postfix-expression}\tcode{.}\grammarterm{id-expression} or +\grammarterm{postfix-expression}\tcode{.}\grammarterm{splice-expression} as \tcode{E1.E2}, \tcode{E1} is called the \defn{object expression}. If the object expression is of scalar type, \tcode{E2} shall name the pseudo-destructor @@ -3985,7 +4222,11 @@ \end{note} \pnum -If \tcode{E2} is a bit-field, \tcode{E1.E2} is a bit-field. The +If \tcode{E2} is a \grammarterm{splice-expression}, +then \tcode{E2} shall designate a member of the type of \tcode{E1}. + +\pnum +If \tcode{E2} designates a bit-field, \tcode{E1.E2} is a bit-field. The type and value category of \tcode{E1.E2} are determined as follows. In the remainder of~\ref{expr.ref}, \cvqual{cq} represents either \keyword{const} or the absence of \keyword{const} and \cvqual{vq} represents @@ -3994,9 +4235,10 @@ in~\ref{basic.type.qualifier}. \pnum -If \tcode{E2} is declared to have type ``reference to \tcode{T}'', then +If \tcode{E2} designates an entity +that is declared to have type ``reference to \tcode{T}'', then \tcode{E1.E2} is an lvalue of type \tcode{T}. -If \tcode{E2} is a static data member, +In that case, if \tcode{E2} designates a static data member, \tcode{E1.E2} designates the object or function to which the reference is bound, otherwise \tcode{E1.E2} designates the object or function to which @@ -4004,11 +4246,11 @@ Otherwise, one of the following rules applies. \begin{itemize} -\item If \tcode{E2} is a static data member and the type of \tcode{E2} +\item If \tcode{E2} designates a static data member and the type of \tcode{E2} is \tcode{T}, then \tcode{E1.E2} is an lvalue; the expression designates the named member of the class. The type of \tcode{E1.E2} is \tcode{T}. -\item If \tcode{E2} is a non-static data member and the type of +\item Otherwise, if \tcode{E2} designates a non-static data member and the type of \tcode{E1} is ``\cvqual{cq1 vq1} \tcode{X}'', and the type of \tcode{E2} is ``\cvqual{cq2 vq2} \tcode{T}'', the expression designates the corresponding member subobject of the object designated by the first expression. If \tcode{E1} @@ -4019,13 +4261,15 @@ is \tcode{volatile}, then \cvqual{vq12} is \keyword{volatile}. Similarly, let the notation \cvqual{cq12} stand for the ``union'' of \cvqual{cq1} and \cvqual{cq2}; that is, if \cvqual{cq1} or \cvqual{cq2} is -\keyword{const}, then \cvqual{cq12} is \keyword{const}. If \tcode{E2} is -declared to be a \keyword{mutable} member, then the type of \tcode{E1.E2} -is ``\cvqual{vq12} \tcode{T}''. If \tcode{E2} is not declared to be a -\keyword{mutable} member, then the type of \tcode{E1.E2} is -``\cvqual{cq12} \cvqual{vq12} \tcode{T}''. - -\item If \tcode{E2} is an overload set, +\keyword{const}, then \cvqual{cq12} is \keyword{const}. +If the entity designated by \tcode{E2} +is declared to be a \keyword{mutable} member, +then the type of \tcode{E1.E2} is ``\cvqual{vq12} \tcode{T}''. +If the entity designated by \tcode{E2} +is not declared to be a \keyword{mutable} member, +then the type of \tcode{E1.E2} is ``\cvqual{cq12} \cvqual{vq12} \tcode{T}''. + +\item If \tcode{E2} denotes an overload set, the expression shall be the (possibly-parenthesized) left-hand operand of a member function call\iref{expr.call}, and function overload resolution\iref{over.match} @@ -4045,26 +4289,30 @@ \end{note} \end{itemize} -\item If \tcode{E2} is a nested type, the expression \tcode{E1.E2} is +\item If \tcode{E2} designates a nested type, the expression \tcode{E1.E2} is ill-formed. -\item If \tcode{E2} is a member enumerator and the type of \tcode{E2} +\item If \tcode{E2} designates a member enumerator and the type of \tcode{E2} is \tcode{T}, the expression \tcode{E1.E2} is a prvalue of type \tcode{T} whose value is the value of the enumerator. + +\item Otherwise, the program is ill-formed. \end{itemize} \pnum -If \tcode{E2} is a non-static member, -the program is ill-formed if the class of which \tcode{E2} is -directly a member is an ambiguous base\iref{class.member.lookup} of -the naming class\iref{class.access.base} of \tcode{E2}. +If \tcode{E2} designates a non-static member +(possibly after overload resolution), +the program is ill-formed if the class of which \tcode{E2} designates +a direct member is an ambiguous base\iref{class.member.lookup} of +the designating class\iref{class.access.base} of \tcode{E2}. \begin{note} The program is also ill-formed if the naming class is an ambiguous base of the class type of the object expression; see~\ref{class.access.base}. \end{note} \pnum -If \tcode{E2} is a non-static member and +If \tcode{E2} designates a non-static member +(possibly after overload resolution) and the result of \tcode{E1} is an object whose type is not similar\iref{conv.qual} to the type of \tcode{E1}, the behavior is undefined. @@ -4940,7 +5188,8 @@ \keyword{alignof} \terminal{(} type-id \terminal{)}\br noexcept-expression\br new-expression\br - delete-expression + delete-expression\br + reflect-expression \end{bnf} \indextext{operator!indirection}% @@ -4996,14 +5245,25 @@ shall be an lvalue of some type \tcode{T}. \begin{itemize} \item -If the operand is a \grammarterm{qualified-id} naming a non-static or variant member \tcode{m} -of some class \tcode{C}, other than an explicit object member function, the result has type ``pointer to member -of class \tcode{C} of type \tcode{T}'' and designates \tcode{C::m}. +If the operand is a \grammarterm{qualified-id} or \grammarterm{splice-expression} +designating a non-static member \tcode{m}, +other than an explicit object member function, +\tcode{m} shall be a direct member of some class \tcode{C} +that is not an anonymous union. +The result has type ``pointer to member of class \tcode{C} of type \tcode{T}'' +and designates \tcode{C::m}. +\begin{note} +A \grammarterm{qualified-id} +that names a member of a namespace-scope anonymous union +is considered to be a class member access expression\iref{expr.prim.id.general} +and cannot be used to form a pointer to member. +\end{note} \item Otherwise, the result has type ``pointer to \tcode{T}'' and points to the designated object\iref{intro.memory} or function\iref{basic.compound}. -If the operand names an explicit object member function\iref{dcl.fct}, -the operand shall be a \grammarterm{qualified-id}. +If the operand designates an explicit object member function\iref{dcl.fct}, +the operand shall be +a \grammarterm{qualified-id} or a \grammarterm{splice-expression}. \begin{note} In particular, taking the address of a variable of type ``\cv{}~\tcode{T}'' yields a pointer of type ``pointer to \cv{}~\tcode{T}''. @@ -5028,8 +5288,9 @@ \pnum A pointer to member is only formed when an explicit \tcode{\&} is used -and its operand is a \grammarterm{qualified-id} not enclosed in -parentheses. +and its operand is +a \grammarterm{qualified-id} or \grammarterm{splice-expression} +not enclosed in parentheses. \begin{note} That is, the expression \tcode{\&(qualified-id)}, where the \grammarterm{qualified-id} is enclosed in parentheses, does not form an @@ -6360,6 +6621,232 @@ the behavior is undefined\iref{new.delete.single,new.delete.array}. \end{note} +\rSec3[expr.reflect]{The reflection operator} + +\begin{bnf} +\nontermdef{reflect-expression}\br + \terminal{\caret\caret} \terminal{::}\br + \terminal{\caret\caret} reflection-name\br + \terminal{\caret\caret} type-id\br + \terminal{\caret\caret} id-expression +\end{bnf} + +\begin{bnf} +\nontermdef{reflection-name}\br + \opt{nested-name-specifier} identifier\br + nested-name-specifier \keyword{template} identifier +\end{bnf} + +\pnum +The unary \tcode{\caret\caret} operator, +called the \defnadj{reflection}{operator}, +yields a prvalue of type \tcode{std::meta::info}\iref{basic.fundamental}. +\begin{note} +This document places no restriction on representing, by reflections, +constructs not described by this document or +using the names of such constructs +as operands of \grammarterm{reflect-expression}s. +\end{note} + +\pnum +The component names of a \grammarterm{reflection-name} +are those of its \grammarterm{nested-name-specifier} (if any) and +its \grammarterm{identifier}. +The terminal name of a \grammarterm{reflection-name} of the form +\grammarterm{nested-name-specifier} \keyword{template} \grammarterm{identifier} +shall denote a template. + +\pnum +A \grammarterm{reflect-expression} is parsed as +the longest possible sequence of tokens +that could syntactically form a \grammarterm{reflect-expression}. +An unparenthesized \grammarterm{reflect-expression} +that represents a template shall not be followed by \tcode{<}. +\begin{example} +\begin{codeblock} +static_assert(std::meta::is_type(^^int())); // \tcode{\caret\caret} applies to the type-id \tcode{int()} + +templatestruct X {}; +consteval bool operator<(std::meta::info, X) { return false; } +consteval void g(std::meta::info r, X xv) { + r == ^^int && true; // error: \tcode{\caret\caret} applies to the \grammarterm{type-id} \tcode{int\&\&} + r == ^^int & true; // error: \tcode{\caret\caret} applies to the type-id \tcode{int\&} + r == (^^int) && true; // OK + r == ^^int &&&& true; // error: \tcode{int \&\&\&\&} is not a valid \grammarterm{type-id} + ^^X < xv; // error: \grammarterm{reflect-expression} that represents a template is followed by \tcode{<} + (^^X) < xv; // OK + ^^X < xv; // OK +} +\end{codeblock} +\end{example} + +\pnum +A \grammarterm{reflect-expression} of the form \tcode{\caret\caret ::} +represents the global namespace. + +\pnum +If a \grammarterm{reflect-expression} $R$ matches +the form \tcode{\caret\caret \grammarterm{reflection-name}}, +it is interpreted as such; +the identifier is looked up and +the representation of $R$ is determined as follows: +\begin{itemize} +\item +If lookup finds a declaration +that replaced a \grammarterm{using-declarator} +during a single search\iref{basic.lookup.general,namespace.udecl}, +$R$ is ill-formed. +\begin{example} +\begin{codeblock} +struct A { struct S {}; }; +struct B : A { using A::S; }; +constexpr std::meta::info r1 = ^^B::S; // error: \tcode{A::S} found through \grammarterm{using-declarator} + +struct C : virtual B { struct S {}; }; +struct D : virtual B, C {}; +D::S s; // OK, names \tcode{C::S} per \ref{class.member.lookup} +constexpr std::meta::info r2 = ^^D::S; // OK, result \tcode{C::S} not found through \grammarterm{using-declarator} +\end{codeblock} +\end{example} +\item +Otherwise, if lookup finds a namespace alias\iref{namespace.alias}, +$R$ represents that namespace alias. +For any other \grammarterm{namespace-name}, +$R$ represents the denoted namespace. +\item +Otherwise, if lookup finds a namespace\iref{namespace.alias}, +$R$ represents that namespace. +\item +Otherwise, if lookup finds a concept\iref{temp.concept}, +$R$ represents the denoted concept. +\item +Otherwise, if lookup finds a template\iref{temp.names}, +the representation of $R$ is determined as follows: +\begin{itemize} +\item +If lookup finds an injected-class-name\iref{class.pre}, then: +\begin{itemize} +\item +If the \grammarterm{reflection-name} is of the form +\tcode{\grammarterm{nested-name-specifier} \keyword{template} \grammarterm{identifier}}, +then $R$ represents the class template named by the injected-class-name. +\item +Otherwise, the injected-class-name shall be unambiguous +when considered as a \grammarterm{type-name} and +$R$ represents the class template specialization so named. +\end{itemize} +\item +Otherwise, if lookup finds an overload set, +that overload set shall contain only +declarations of a unique function template F; +$R$ represents F. +\item +Otherwise, if lookup finds +a class template, variable template, or alias template, +$R$ represents that template. +\begin{note} +Lookup never finds a partial or explicit specialization. +\end{note} +\end{itemize} +\item +Otherwise, if lookup finds a type alias $A$, +$R$ represents the underlying entity of $A$ +if $A$ was introduced by the declaration of a template parameter; +otherwise, $R$ represents $A$. +\item +Otherwise, if lookup finds a class or an enumeration, +$R$ represents the denoted type. +\item +Otherwise, if lookup finds a class member of an anonymous union\iref{class.union.anon}, $R$ represents that class member. +\item +Otherwise, +the \grammarterm{reflection-name} shall be an \grammarterm{id-expression} \tcode{I} +and $R$ is \tcode{\caret\caret I} (see below). +\end{itemize} + +\pnum +A \grammarterm{reflect-expression} $R$ of the form +\tcode{\caret\caret \grammarterm{type-id}} +represents an entity determined as follows: +\begin{itemize} +\item +If the \grammarterm{type-id} designates +a placeholder type\iref{dcl.spec.auto.general}, +$R$ is ill-formed. +\item +Otherwise, if the \grammarterm{type-id} names a type alias +that is a specialization of an alias template\iref{temp.alias}, +$R$ represents that type alias. +\item +Otherwise, $R$ represents the type denoted by the \grammarterm{type-id}. +\end{itemize} + +\pnum +A \grammarterm{reflect-expression} $R$ of the form +\tcode{\caret\caret \grammarterm{id-expression}} +represents an entity determined as follows: +\begin{itemize} +\item +If the \grammarterm{id-expression} denotes +\begin{itemize} +\item +a variable declared by +an \grammarterm{init-capture}\iref{expr.prim.lambda.capture}, +\item +a function-local predefined variable\iref{dcl.fct.def.general}, +\item +a local parameter introduced by +a \grammarterm{requires-expression}\iref{expr.prim.req}, or +\item +a local entity $E$\iref{basic.pre} for which a lambda scope intervenes +between the point at which $E$ was introduced and $R$, +then $R$ is ill-formed. +\end{itemize} +\item +Otherwise, if the \grammarterm{id-expression} denotes an overload set $S$, +overload resolution for the expression \tcode{\&S} with no target +shall select a unique function\iref{over.over}; +$R$ represents that function. +\item +Otherwise, if the \grammarterm{id-expression} denotes +a variable, structured binding, enumerator, or non-static data member, +$R$ represents that entity. +\item +Otherwise, $R$ is ill-formed. +\begin{note} +This includes \grammarterm{unqualified-id}s +that name a constant template parameter and +\grammarterm{pack-index-expression}s. +\end{note} +\end{itemize} +The \grammarterm{id-expression} of +a \grammarterm{reflect-expression} is an unevaluated operand\iref{expr.context}. +\begin{example} +\begin{codeblock} +template void fn() requires (^^T != ^^int); +template void fn() requires (^^T == ^^int); +template void fn() requires (sizeof(T) == sizeof(int)); + +constexpr std::meta::info a = ^^fn; // OK +constexpr std::meta::info b = ^^fn; // error: ambiguous + +constexpr std::meta::info c = ^^std::vector; // OK + +template +struct S { + static constexpr std::meta::info r = ^^T; + using type = T; +}; +static_assert(S::r == ^^int); +static_assert(^^S::type != ^^int); + +typedef struct X {} Y; +typedef struct Z {} Z; +constexpr std::meta::info e = ^^Y; // OK, represents the type alias \tcode{Y} +constexpr std::meta::info f = ^^Z; // OK, represents the type alias \tcode{Z}, not the type\iref{basic.lookup.general} +\end{codeblock} +\end{example} + \rSec2[expr.cast]{Explicit type conversion (cast notation)}% \indextext{expression!cast|(} @@ -7146,6 +7633,19 @@ Two operands of type \tcode{std::nullptr_t} or one operand of type \tcode{std::nullptr_t} and the other a null pointer constant compare equal. +\pnum +If both operands are of type \tcode{std::meta::info}, +they compare equal if both operands +\begin{itemize} +\item are null reflection values, +\item represent values that are template-argument-equivalent\iref{temp.type}, +\item represent the same object, +\item represent the same entity, +\item represent the same direct base class relationship, or +\item represent equal data member descriptions\iref{class.mem.general}, +\end{itemize} +and they compare unequal otherwise. + \pnum If two operands compare equal, the result is \keyword{true} for the \tcode{==} operator and \keyword{false} for the \tcode{!=} operator. If two operands @@ -8191,6 +8691,11 @@ that would throw an exception where no definition of the exception type is reachable; +\item +an expression that would produce an injected declaration (see below), +unless $E$ is the corresponding expression of +a \grammarterm{consteval-block-declaration}\iref{dcl.pre}; + \item an \grammarterm{asm-declaration}\iref{dcl.asm}; @@ -8328,7 +8833,8 @@ \pnum During the evaluation of an expression $E$ as a core constant expression, -all \grammarterm{id-expression}s and uses of \tcode{*\keyword{this}} +all \grammarterm{id-expression}s, \grammarterm{splice-expression}s, and +uses of \tcode{*\keyword{this}} that refer to an object or reference whose lifetime did not begin with the evaluation of $E$ are treated as referring to a specific instance of that object or reference @@ -8481,8 +8987,30 @@ \pnum A \defnadj{constant}{expression} is either -a glvalue core constant expression that refers to -an object or a non-immediate function, or +\begin{itemize} +\item +a glvalue core constant expression $E$ for which +\begin{itemize} +\item +$E$ refers to a non-immediate function +\item +$E$ designates an object \tcode{o}, and +if the complete object of \tcode{o} is of consteval-only type then so is $E$, +\begin{example} +\begin{codeblock} +struct Base { }; +struct Derived : Base { std::meta::info r; }; + +consteval const Base& fn(const Derived& derived) { return derived; } + +constexpr Derived obj{.r=^^::}; // OK +constexpr const Derived& d = obj; // OK +constexpr const Base& b = fn(obj); // error: not a constant expression because \tcode{Derived} is a consteval-only type but \tcode{Base} is not. +\end{codeblock} +\end{example} +\end{itemize} +or +\item a prvalue core constant expression whose result object\iref{basic.lval} satisfies the following constraints: \begin{itemize} @@ -8494,7 +9022,21 @@ no constituent value of pointer type is a pointer to an immediate function or an invalid pointer value\iref{basic.compound}, and \item -no constituent value of pointer-to-member type designates an immediate function. +no constituent value of pointer-to-member type designates an immediate function, and +\item +unless the value is of consteval-only type, +\begin{itemize} +\item +no constituent value of pointer-to-member type points to +a direct member of a consteval-only class type +\item +no constituent value of pointer type points to or past an object +whose complete object is of consteval-only type, and +\item +no constituent reference refers to an object +whose complete object is of consteval-only type. +\end{itemize} +\end{itemize} \end{itemize} \begin{note} A glvalue core constant expression @@ -8570,17 +9112,17 @@ \indexdefn{conversion!immediate-escalating}% \indexdefn{immediate-escalating!expression|see{expression, immediate-escalating}}% \indexdefn{immediate-escalating!conversion|see{conversion, immediate-escalating}}% -An expression or conversion is \defn{immediate-escalating} -if it is not initially in an immediate function context -and it is either +A potentially-evaluated expression or conversion is \defn{immediate-escalating} +if it is neither initially in an immediate function context +nor a subexpression of an immediate invocation, and \begin{itemize} \item -a potentially-evaluated \grammarterm{id-expression} -that denotes an immediate function -that is not a subexpression of an immediate invocation, or +it is an \grammarterm{id-expression} or \grammarterm{splice-expression} +that designates an immediate function, \item -an immediate invocation that is not a constant expression -and is not a subexpression of an immediate invocation. +it is an immediate invocation that is not a constant expression, or +\item +it is of consteval-only type\iref{basic.types.general}. \end{itemize} \pnum @@ -8601,14 +9143,18 @@ in an immediate-escalating function. \pnum -An \defnadj{immediate}{function} is a function or constructor that is +An \defnadj{immediate}{function} is a function or constructor that is either \begin{itemize} \item declared with the \keyword{consteval} specifier, or \item an immediate-escalating function \tcode{\placeholder{F}} -whose function body contains an immediate-escalating expression \tcode{\placeholder{E}} -such that \tcode{\placeholder{E}}'s innermost enclosing non-block scope +whose function body contains either +\begin{itemize} +\item an immediate-escalating expression or +\item a definition of a non-constexpr variable with consteval-only type +\end{itemize} +whose innermost enclosing non-block scope is \tcode{\placeholder{F}}'s function parameter scope. \begin{tailnote} Default member initializers used to initialize @@ -8682,7 +9228,6 @@ \end{codeblock} \end{example} - \pnum An expression or conversion is \defn{manifestly constant-evaluated} if it is: @@ -8730,6 +9275,143 @@ is evaluated even in an unevaluated operand\iref{term.unevaluated.operand}. \end{note} +\pnum +The evaluation of an expression can introduce +one or more \defnadjx{injected}{declarations}{declaration}. +The evaluation is said to \defn{produce} the declarations. +\begin{note} +An invocation of +the library function template \tcode{std::meta::define_aggregate} +produces an injected declaration\iref{meta.reflection.define.aggregate}. +\end{note} +Each such declaration has +\begin{itemize} +\item +an associated \defnadj{synthesized}{point}, +which follows the last non-synthesized program point +in the translation unit containing that declaration, and +\item +an associated \defnadj{characteristic}{sequence} of values. +\end{itemize} +\begin{note} +Special rules concerning reachability +apply to synthesized points\iref{module.reach}. +\end{note} +\begin{note} +The program is ill-formed +if injected declarations with different characteristic sequences +define the same entity in different translation units\iref{basic.def.odr}. +\end{note} + +\pnum +A member of an entity defined by an injected declaration +shall not have a name reserved to the implementation\iref{lex.name}; +no diagnostic is required. + +\pnum +Let $C$ be a \grammarterm{consteval-block-declaration}, +the evaluation of whose corresponding expression +produces an injected declaration for an entity $E$. +The program is ill-formed if either +\begin{itemize} +\item +$C$ is enclosed by a scope associated with $E$ or +\item +letting $P$ be a point whose immediate scope is that to which $E$ belongs, +there is a function parameter scope or class scope +that encloses exactly one of $C$ or $P$. +\end{itemize} +\begin{example} +\begin{codeblock} +struct S0 { + consteval { + std::meta::define_aggregate(^^S0, {}); // error: scope associated with S0 encloses the consteval block + } +}; + +struct S1; +consteval { std::meta::define_aggregate(^^S1, {}); } // OK + +template consteval void tfn1() { + std::meta::define_aggregate(R, {}); +} + +struct S2; +consteval { tfn1<^^S2>(); } // OK + +template consteval void tfn2() { + consteval { std::meta::define_aggregate(R, {}); } +} + +struct S3; +consteval { tfn2<^^S3>(); } + // error: function parameter scope of \tcode{tfn2<\caret\caret S3>} intervenes between the declaration of \tcode{S3} + // and the consteval block that produces the injected declaration + +template struct TCls { + struct S4; + static void sfn() requires ([] { + consteval { std::meta::define_aggregate(^^S4, {}); } + return true; + }()) { } +}; + +consteval { TCls::sfn(); } // error: \tcode{TCls::S4} is not enclosed by \grammarterm{requires-clause} lambda + +struct S5; +struct Cls { + consteval { std::meta::define_aggregate(^^S5, {}); } // error: \tcode{S5} is not enclosed by class \tcode{Cls} +}; + +struct S6; +consteval { // \#1 + struct S7; // local class + std::meta::define_aggregate(^^S7, {}); + // error: consteval block \#1 does not enclose itself, but encloses \tcode{S7} + consteval { // \#2 + std::meta::define_aggregate(^^S6, {}); + // error: consteval block \#1 encloses consteval block \#2 but not \tcode{S6} + std::meta::define_aggregate(^^S7, {}); // OK, consteval block \#1 encloses both \#2 and \tcode{S7} + } +} +\end{codeblock} +\end{example} + +\pnum +The \defn{evaluation context} is a set of program points +that determines the behavior of certain functions +used for reflection\iref{meta.reflection}. +During the evaluation $V$ of an expression $E$ as a core constant expression, +the evaluation context of an evaluation $X$\iref{intro.execution} +consists of the following points: +\begin{itemize} +\item +The program point $\textit{EVAL-PT}(L)$, +where $L$ is the point at which $E$ appears, and +where $\textit{EVAL-PT}(P)$, for a point $P$, +is a point $R$ determined as follows: +\begin{itemize} +\item +If a potentially-evaluated subexpression\iref{intro.execution} of +a default member initializer $I$ appears at $P$, and +a (possibly aggregate) initialization during $V$ is using $I$, +then $R$ is $\textit{EVAL-PT}(Q)$ +where $Q$ is the point at which that initialization appears. +\item +Otherwise, if a potentially-evaluated subexpression of +a default argument\iref{dcl.fct.default} appears at $P$, and +an invocation of a function\iref{expr.call} during $V$ +is using that default argument, +then $R$ is $\textit{EVAL-PT}(Q)$ +where $Q$ is the point at which that invocation appears. +\item +Otherwise, $R$ is $P$. +\end{itemize} +\item +Each synthesized point corresponding to an injected declaration produced by +any evaluation sequenced before $X$\iref{intro.execution}. +\end{itemize} + \pnum \indextext{expression!potentially constant evaluated}% An expression or conversion is \defn{potentially constant evaluated} diff --git a/source/lex.tex b/source/lex.tex index 6cf011e432..de8a65945c 100644 --- a/source/lex.tex +++ b/source/lex.tex @@ -210,43 +210,84 @@ only, and does not specify any particular implementation. \end{note} -\item Translated translation units and instantiation units are combined -as follows: -\begin{note} -Some or all of these can be supplied from a -library. -\end{note} -Each translated translation unit is examined to -produce a list of required instantiations. +While the tokens constituting translation units +are being analyzed and translated, +required instantiations are performed. \begin{note} This can include instantiations which have been explicitly requested\iref{temp.explicit}. \end{note} -The definitions of the -required templates are located. It is \impldef{whether source of translation units must -be available to locate template definitions} whether the -source of the translation units containing these definitions is required -to be available. -\begin{note} -An implementation can choose to encode sufficient -information into the translated translation unit so as to ensure the -source is not required here. -\end{note} -All the required instantiations -are performed to produce -\defn{instantiation units}. + +The contexts from which instantiations may be performed +are determined by their respective points of instantiation\iref{temp.point}. + \begin{note} -These are similar -to translated translation units, but contain no references to -uninstantiated templates and no template definitions. +Other requirements in this document can further constrain +the context from which an instantiation can be performed. +For example, a constexpr function template specialization +might have a point of instantation at the end of a translation unit, +but its use in certain constant expressions could require +that it be instantiated at an earlier point\iref{temp.inst}. \end{note} -The -program is ill-formed if any instantiation fails. + +Each instantiation results in new program constructs. +The program is ill-formed if any instantiation fails. + +During the analysis and translation of tokens, +certain expressions are evaluated\iref{expr.const}. +Constructs appearing at a program point $P$ are analyzed +in a context where each side effect of evaluating an expression $E$ +as a full-expression is complete if and only if +\begin{itemize} +\item +$E$ is the expression corresponding to +a \grammarterm{consteval-block-declaration}\iref{dcl.pre}, and +\item +either that \grammarterm{consteval-block-declaration} or +the template definition from which it is instantiated +is reachable from\iref{module.reach} +\begin{itemize} +\item +$P$, or +\item +the point immediately following +the \grammarterm{class-specifier} of the outermost class +for which $P$ is in a complete-class context\iref{class.mem.general}. +\end{itemize} +\end{itemize} +\begin{example} +\begin{codeblock} +class S { + class Incomplete; + + class Inner { + void fn() { + /* P1 */ Incomplete i; // OK + } + }; /* P2 */ + + consteval { + define_aggregate(^^Incomplete, {}); + } +}; /* P3 */ +\end{codeblock} +Constructs at P1 are analyzed in a context +where the side effect of the call to \tcode{define_aggregate} is evaluated +because +\begin{itemize} +\item +$E$ is the expression corresponding to a consteval block, and +\item +P1 is in a complete-class context of \tcode{S} and +the consteval block is reachable from P3. +\end{itemize} +\end{example} \item \indextext{linking}% -All external entity references are resolved. Library +Translated translation units are combined, and +all external entity references are resolved. Library components are linked to satisfy external references to entities not defined in the current translation. All such translator output is collected into a program image which contains information @@ -584,6 +625,16 @@ is neither \tcode{:} nor \tcode{>}, the \tcode{<} is treated as a preprocessing token by itself and not as the first character of the alternative token \tcode{<:}. +\item +Otherwise, if the next three characters are \tcode{[::} and +the subsequent character is not \tcode{:}, or +if the next three characters are \tcode{[:>}, +the \tcode{[} is treated as a preprocessing token by itself and +not as the first character of the preprocessing token \tcode{[:}. +\begin{note} +The tokens \tcode{[:} and \tcode{:]} cannot be composed from digraphs. +\end{note} + \item Otherwise, the next preprocessing token is the longest sequence of characters that could constitute a preprocessing token, even if that @@ -743,12 +794,12 @@ \begin{bnf} \microtypesetup{protrusion=false} \nontermdef{operator-or-punctuator} \textnormal{one of}\br - \terminal{\{ \ \ \ \ \ \ \ \} \ \ \ \ \ \ \ [ \ \ \ \ \ \ \ ] \ \ \ \ \ \ \ ( \ \ \ \ \ \ \ )}\br + \terminal{\{ \ \ \ \ \ \ \ \} \ \ \ \ \ \ \ [ \ \ \ \ \ \ \ ] \ \ \ \ \ \ \ ( \ \ \ \ \ \ \ ) \ \ \ \ \ \ \ [: \ \ \ \ \ \ :]}\br \terminal{<\% \ \ \ \ \ \ \%> \ \ \ \ \ \ <: \ \ \ \ \ \ :> \ \ \ \ \ \ ; \ \ \ \ \ \ \ : \ \ \ \ \ \ \ ...}\br \terminal{? \ \ \ \ \ \ \ :: \ \ \ \ \ \ . \ \ \ \ \ \ \ .* \ \ \ \ \ \ -> \ \ \ \ \ \ ->* \ \ \ \ \ \~}\br \terminal{! \ \ \ \ \ \ \ + \ \ \ \ \ \ \ - \ \ \ \ \ \ \ * \ \ \ \ \ \ \ / \ \ \ \ \ \ \ \% \ \ \ \ \ \ \ \caret{} \ \ \ \ \ \ \ \& \ \ \ \ \ \ \ |}\br \terminal{= \ \ \ \ \ \ \ += \ \ \ \ \ \ -= \ \ \ \ \ \ *= \ \ \ \ \ \ /= \ \ \ \ \ \ \%= \ \ \ \ \ \ \caret{}= \ \ \ \ \ \ \&= \ \ \ \ \ \ |=}\br - \terminal{== \ \ \ \ \ \ != \ \ \ \ \ \ < \ \ \ \ \ \ \ > \ \ \ \ \ \ \ <= \ \ \ \ \ \ >= \ \ \ \ \ \ <=> \ \ \ \ \ \&\& \ \ \ \ \ \ ||}\br + \terminal{== \ \ \ \ \ \ != \ \ \ \ \ \ < \ \ \ \ \ \ \ > \ \ \ \ \ \ \ <= \ \ \ \ \ \ >= \ \ \ \ \ \ <=> \ \ \ \ \ \&\& \ \ \ \ \ \ || \ \ \ \ \ \ \caret{}\caret{}}\br \terminal{<< \ \ \ \ \ \ >> \ \ \ \ \ \ <<= \ \ \ \ \ >>= \ \ \ \ \ ++ \ \ \ \ \ \ -- \ \ \ \ \ \ ,}\br \terminal{\keyword{and} \ \ \ \ \ \keyword{or} \ \ \ \ \ \ \keyword{xor} \ \ \ \ \ \keyword{not} \ \ \ \ \ \keyword{bitand} \ \ \keyword{bitor} \ \ \ \keyword{compl}}\br \terminal{\keyword{and_eq} \ \ \keyword{or_eq} \ \ \ \keyword{xor_eq} \ \ \keyword{not_eq}} diff --git a/source/modules.tex b/source/modules.tex index a0386b38ca..cfe20205b1 100644 --- a/source/modules.tex +++ b/source/modules.tex @@ -148,7 +148,9 @@ it is attached to the module to which the friend is attached\iref{basic.link}. \item Otherwise, if the declaration \begin{itemize} -\item is a \grammarterm{namespace-definition} with external linkage or +\item declares a namespace whose name has external linkage, +\item declares a type alias, +\item declares a namespace alias, or \item appears within a \grammarterm{linkage-specification}\iref{dcl.link} \end{itemize} it is attached to the global module. @@ -262,9 +264,10 @@ \pnum If an exported declaration is a \grammarterm{using-declaration}\iref{namespace.udecl} and is not within a header unit, -all entities to which all of the -\grammarterm{using-declarator}{s} ultimately refer (if any) -shall have been introduced with a name having external linkage. +all entities named by the +\grammarterm{using-declarator}{s} (if any) +shall either be a type alias or +have been introduced with a name having external linkage. \begin{example} \begin{codeblocktu}{Source file \tcode{"b.h"}} int f(); @@ -296,9 +299,8 @@ \end{codeblocktu} \end{example} \begin{note} -These constraints do not apply to -type names introduced by \keyword{typedef} declarations -and \grammarterm{alias-declaration}{s}. +The underlying entity of an exported type alias +need not have a name with external linkage. \begin{example} \begin{codeblock} export module M; @@ -312,13 +314,14 @@ A redeclaration of an entity $X$ is implicitly exported if $X$ was introduced by an exported declaration; -otherwise it shall not be exported unless it is a namespace. +otherwise it shall not be exported +unless it is a type alias, a namespace, or a namespace alias. \begin{example} \begin{codeblock} export module M; struct S { int n; }; typedef S S; -export typedef S S; // OK, does not redeclare an entity +export typedef S S; // OK export struct S; // error: exported declaration follows non-exported declaration namespace N { // external linkage, attached to global module, not exported void f(); @@ -698,12 +701,22 @@ that does not denote a dependent type is replaced by its denoted type prior to this determination, -and \item whether a non-value-dependent constant expression is replaced by the result of constant evaluation -prior to this determination. +prior to this determination, +and + +\item +whether +a \grammarterm{splice-expression}, +a \grammarterm{splice-type-specifier}, +a \grammarterm{splice-scope-specifier}, or +any \grammarterm{splice-specifier} or +\grammarterm{splice-specialization-specifier} +outside of the preceding is replaced in any non-dependent context +by the construct that it designates prior to this determination. \end{itemize} \pnum @@ -878,8 +891,9 @@ \pnum During the implicit definition of a defaulted function\iref{special,class.compare.default}, -the instantiation context is the union of +the instantiation context contains each point in the instantiation context from the definition of the class and +each point in the instantiation context of the program construct that resulted in the implicit definition of the defaulted function. @@ -887,7 +901,7 @@ During the implicit instantiation of a template whose point of instantiation is specified as that of an enclosing specialization\iref{temp.point}, -the instantiation context is the union of +the instantiation context contains each point in the instantiation context of the enclosing specialization and, if the template is defined in a module interface unit of a module $M$ and the point of instantiation is not in a module interface unit of $M$, @@ -900,18 +914,35 @@ During the implicit instantiation of a template that is implicitly instantiated because it is referenced from within the implicit definition of a defaulted function, -the instantiation context is the instantiation context of +the instantiation context contains each point in the instantiation context of the defaulted function. \pnum During the instantiation of any other template specialization, -the instantiation context comprises the point of instantiation +the instantiation context contains the point of instantiation of the template. +\pnum +During the implicit instantiation of any construct +that resulted from the evaluation of an expression +as a core constant expression, +the instantiation context contains +each point in the evaluation context\iref{expr.const}. +\begin{note} +Implicit instantiations can result +from invocations of library functions\iref{meta.reflection}. +The evaluation context can include synthesized points +associated with injected declarations +produced by \tcode{std::meta::define_aggregate}\iref{meta.reflection.define.aggregate}. +\end{note} + \pnum In any other case, the instantiation context at a point within the program -comprises that point. +contains that point. + +\pnum +The instantiation context contains only the points specified above. \pnum \begin{example} @@ -1008,13 +1039,42 @@ A declaration $D$ is \defnx{reachable from}{reachable from!declaration} a point $P$ if \begin{itemize} +\item +$P$ is a non-synthesized point and +\begin{itemize} \item $D$ appears prior to $P$ in the same translation unit, or \item $D$ is not discarded\iref{module.global.frag}, appears in a translation unit that is reachable from $P$, and -does not appear within a \grammarterm{private-module-fragment}. +does not appear within a \grammarterm{private-module-fragment}; or +\end{itemize} +\item +$D$ is the injected declaration +for which $P$ is the corresponding synthesized point. \end{itemize} +\begin{example} +\begin{codeblock} +class Incomplete; + +consteval { + int n = nonstatic_data_members_of( + define_aggregate(^^Incomplete, {data_member_spec(^^int, {.name="x"})}), + std::meta::access_context::current() + ).size(); + + Incomplete y; // error: type of \tcode{y} is incomplete +} +/* P */ +\end{codeblock} +The value of \tcode{n} is 1. +The member \tcode{Incomplete::x} +members-of-precedes\iref{meta.reflection.member.queries} +the synthesized point P associated with the injected declaration +produced by the call to \tcode{define_aggregate}. +\end{example} + +\pnum A declaration is \defnx{reachable}{reachable!declaration} if it is reachable from any point in the instantiation context\iref{module.context}. diff --git a/source/overloading.tex b/source/overloading.tex index 5343a015a7..5881618fc0 100644 --- a/source/overloading.tex +++ b/source/overloading.tex @@ -16,13 +16,18 @@ \end{note} \pnum -When a function is named in a call, which function +When a function is designated in a call, which function declaration is being referenced and the validity of the call are determined by comparing the types of the arguments at the point of use with the types of the parameters in the declarations in the overload set. This function selection process is called \defn{overload resolution} and is defined in~\ref{over.match}. +\begin{note} +Overload sets are formed by \grammarterm{id-expression}s +naming functions and function templates and +by \grammarterm{splice-expression}s designating entities of the same kinds. +\end{note} \begin{example} \indextext{overloading!example of}% \begin{codeblock} @@ -380,13 +385,13 @@ overload set in other contexts is described in \ref{over.over}. \end{note} -\rSec4[over.call.func]{Call to named function} +\rSec4[over.call.func]{Call to designated function} \pnum -Of interest in~\ref{over.call.func} are only those function calls in -which the \grammarterm{postfix-expression} -ultimately contains an \grammarterm{id-expression} that -denotes one or more functions. +Of interest in~\ref{over.call.func} are only those function calls +in which the \grammarterm{postfix-expression} ultimately contains +an \grammarterm{id-expression} or \grammarterm{splice-expression} +that designates one or more functions. Such a \grammarterm{postfix-expression}, perhaps nested arbitrarily deep in @@ -395,8 +400,11 @@ \begin{ncbnf} postfix-expression:\br postfix-expression \terminal{.} id-expression\br + postfix-expression \terminal{.} splice-expression\br postfix-expression \terminal{->} id-expression\br - primary-expression + postfix-expression \terminal{->} splice-expression\br + id-expression\br + splice-expression \end{ncbnf} These represent two syntactic subcategories of function calls: @@ -404,7 +412,8 @@ \pnum In qualified function calls, -the function is named by an \grammarterm{id-expression} +the function is designated by +an \grammarterm{id-expression} or \grammarterm{splice-expression} $E$ preceded by an \tcode{->} or \tcode{.} operator. Since the construct @@ -433,8 +442,11 @@ resolution for both glvalue and class prvalue objects. \end{footnote} -The function declarations found by name lookup\iref{class.member.lookup} -constitute the set of candidate functions. +The set of candidate functions either +is the set found by name lookup\iref{class.member.lookup} +if $E$ is an \grammarterm{id-expression} or +is the set determined as specified in~\ref{expr.prim.splice} +if $E$ is a \grammarterm{splice-expression}. The argument list is the \grammarterm{expression-list} in the call augmented by the addition of the left operand of @@ -444,16 +456,20 @@ implied object argument\iref{over.match.funcs}. \pnum -In unqualified function calls, the function is named by a -\grammarterm{primary-expression}. -The function declarations found by name lookup\iref{basic.lookup} constitute the -set of candidate functions. -Because of the rules for name lookup, the set of candidate functions +In unqualified function calls, the function is designated by +an \grammarterm{id-expression} or a \grammarterm{splice-expression} $E$ +The set of candidate functions either +is the set found by name lookup\iref{basic.lookup} +if $E$ is an \grammarterm{id-expression} or +is the set determined as specified in~\ref{expr.prim.splice} +if $E$ is a \grammarterm{splice-expression}. +The set of candidate functions consists either entirely of non-member functions or entirely of member functions of some class \tcode{T}. In the former case or -if the \grammarterm{primary-expression} is the address of an overload set, +if $E$ is either a \grammarterm{splice-expression} or +the address of an overload set, the argument list is the same as the \grammarterm{expression-list} @@ -1210,7 +1226,8 @@ \pnum When resolving a placeholder for a deduced class type\iref{dcl.type.class.deduct} -where the \grammarterm{template-name} names a primary class template \tcode{C}, +where the \grammarterm{template-name} or \grammarterm{splice-type-specifier} +designates a primary class template \tcode{C}, a set of functions and function templates, called the guides of \tcode{C}, is formed comprising: \begin{itemize} @@ -1412,7 +1429,9 @@ \pnum When resolving a placeholder for a deduced class type\iref{dcl.type.simple} -where the \grammarterm{template-name} names an alias template \tcode{A}, +where +the \grammarterm{template-name} or \grammarterm{splice-type-specifier} +designates an alias template \tcode{A}, the \grammarterm{defining-type-id} of \tcode{A} must be of the form \begin{ncsimplebnf} \opt{\keyword{typename}} \opt{nested-name-specifier} \opt{\keyword{template}} simple-template-id @@ -1698,13 +1717,76 @@ any argument for which there is no corresponding parameter is considered to ``match the ellipsis''\iref{over.ics.ellipsis}. \item -A candidate function having more than $m$ parameters is viable -only if all parameters following the $m^\text{th}$ -have default arguments\iref{dcl.fct.default}. +A candidate function \tcode{C} having more than $m$ parameters is viable +only if the set of scopes $G$, as defined below, is not empty. +$G$ consists of every scope $X$ that satisfies all of the following: +\begin{itemize} +\item There is a declaration of \tcode{C}, whose host scope is $X$, +considered by the overload resolution. +\item For every $k^\textrm{th}$ parameter $P$ where $k$ > $m$, +there is a reachable declaration, whose host scope is $X$, +that specifies a default argument\iref{dcl.fct.default} for $P$. +\end{itemize} +If \tcode{C} is selected as the best viable function\iref{over.match.best}: +\begin{itemize} +\item +$G$ shall contain exactly one scope (call it $S$). +\item +If the candidates are denoted by a \grammarterm{splice-expression}, +then $S$ shall not be a block scope. +\item +The default arguments used in the call \tcode{C} are +the default arguments specified by +the reachable declarations whose host scope is $S$. +\end{itemize} For the purposes of overload resolution, the parameter list is truncated on the right, so that there are exactly $m$ parameters. \end{itemize} +\begin{example} +\begin{codeblock} +namespace A { + extern "C" void f(int, int = 5); + extern "C" void f(int = 6, int); +} +namespace B { + extern "C" void f(int, int = 7); +} + +void use() { + [:^^A::f:](3, 4); // OK, default argument was not used for viability + [:^^A::f:](3); // error: default argument provided by declarations from two scopes + [:^^A::f:](); // OK, default arguments provided by declarations in the scope of \tcode{A} + + using A::f; + using B::f; + f(3, 4); // OK, default argument was not used for viability + f(3); // error: default argument provided by declaration from two scopes + f(); // OK, default arguments provided by declarations in the scope of \tcode{A} + + void g(int = 8); + g(); // OK + [:^^g:](); // error: host scope is block scope +} + +void h(int = 7); +constexpr std::meta::info r = ^^h; +void poison() { + void h(int = 8); + h(); // OK, calls \tcode{h(8)} + [:^^h:](); // error: default argument provided by declarations from two scopes +} +void call_h() { + [:^^h:](); // error: default argument provided by declarations from two scopes + [:r:](); // error: default argument provided by declarations from two scopes +} + +template +int k(int = 3, Ts...); +int i = k(); // error: no default argument for the second parameter +int j = k<>(); // OK +\end{codeblock} +\end{example} \pnum Second, for a function to be viable, if it has associated constraints\iref{temp.constr.decl}, @@ -2006,29 +2088,10 @@ \end{example} \pnum -If the best viable function resolves to a function -for which multiple declarations were found, and -if any two of these declarations inhabit different scopes and -specify a default argument that made the function viable, -the program is ill-formed. -\begin{example} -\begin{codeblock} -namespace A { - extern "C" void f(int = 5); -} -namespace B { - extern "C" void f(int = 5); -} - -using A::f; -using B::f; - -void use() { - f(3); // OK, default argument was not used for viability - f(); // error: found default argument twice -} -\end{codeblock} -\end{example} +\begin{note} +If the best viable function was made viable by one or more default arguments, +additional requirements apply\iref{over.match.viable}. +\end{note} \rSec3[over.best.ics]{Implicit conversion sequences}% @@ -3103,8 +3166,8 @@ \indextext{overloaded function!address of} \pnum -An \grammarterm{id-expression} -whose terminal name refers to an overload set $S$ and +An expression +that designates an overload set $S$ and that appears without arguments is resolved to a function, @@ -3134,7 +3197,7 @@ If the target type contains a placeholder type, placeholder type deduction is performed\iref{dcl.type.auto.deduct}, and the remainder of this subclause uses the target type so deduced. -The \grammarterm{id-expression} can be preceded by the \tcode{\&} operator. +The expression can be preceded by the \tcode{\&} operator. \begin{note} Any redundant set of parentheses surrounding the function name is ignored\iref{expr.prim.paren}. @@ -3919,7 +3982,7 @@ \pnum For every \tcode{\placeholder{T}}, where \tcode{\placeholder{T}} -is a pointer-to-member type or \tcode{std::nullptr_t}, +is a pointer-to-member type, \tcode{std::meta::info}, or \tcode{std::nullptr_t}, there exist candidate operator functions of the form \begin{codeblock} bool operator==(@\placeholder{T}@, @\placeholder{T}@); diff --git a/source/preprocessor.tex b/source/preprocessor.tex index ee7959abeb..b44e46ed6e 100644 --- a/source/preprocessor.tex +++ b/source/preprocessor.tex @@ -2321,6 +2321,7 @@ \defnxname{cpp_impl_coroutine} & \tcode{201902L} \\ \rowsep \defnxname{cpp_impl_destroying_delete} & \tcode{201806L} \\ \rowsep \defnxname{cpp_impl_three_way_comparison} & \tcode{201907L} \\ \rowsep +\defnxname{cpp_impl_reflection} & \tcode{202506L} \\ \rowsep \defnxname{cpp_implicit_move} & \tcode{202207L} \\ \rowsep \defnxname{cpp_inheriting_constructors} & \tcode{201511L} \\ \rowsep \defnxname{cpp_init_captures} & \tcode{201803L} \\ \rowsep diff --git a/source/templates.tex b/source/templates.tex index bf283e46da..f674971f16 100644 --- a/source/templates.tex +++ b/source/templates.tex @@ -331,6 +331,10 @@ concept template parameters are collectively referred to as \defnadj{template}{template parameters}. +\pnum +The \grammarterm{nested-name-specifier} of a \grammarterm{type-constraint}, +if any, shall not be dependent. + \pnum A concept template parameter shall not have associated constraints\iref{temp.constr.decl}. @@ -726,7 +730,16 @@ \pnum A \tcode{<} is interpreted as the delimiter of a \grammarterm{template-argument-list} -if it follows a name that is not a \grammarterm{conversion-function-id} and +if either +\begin{itemize} +\item +it follows a \grammarterm{splice-specifier} that either +\begin{itemize} +\item appears in a type-only context or +\item is preceded by \keyword{template} or \keyword{typename}, or +\end{itemize} +\item +it follows a name that is not a \grammarterm{conversion-function-id} and \begin{itemize} \item that follows the keyword \keyword{template} or a \tcode{\~} @@ -745,6 +758,7 @@ in a type-only context other than a \grammarterm{nested-name-specifier}\iref{temp.res}. \end{itemize} +\end{itemize} \begin{note} If the name is an \grammarterm{identifier}, it is then interpreted as a \grammarterm{template-name}. @@ -763,7 +777,11 @@ T* p2 = p->template alloc<200>(); // OK, \tcode{<} starts template argument list T::adjust<100>(); // error: \tcode{<} means less than T::template adjust<100>(); // OK, \tcode{<} starts template argument list -} + + static constexpr std::meta::info r = ^^T::adjust; + T* p3 = [:r:]<200>(); // error: \tcode{<} means less than + T* p4 = template [:r:]<200>(); // OK, \tcode{<} starts template argument list +}} \end{codeblock} \end{example} @@ -776,20 +794,21 @@ A \tcode{>} that encloses the \grammarterm{type-id} of a \keyword{dynamic_cast}, \keyword{static_cast}, \keyword{reinterpret_cast} or \keyword{const_cast}, or which encloses the \grammarterm{template-argument}{s} -of a subsequent \grammarterm{template-id}, is considered nested for the purpose -of this description. +of a subsequent \grammarterm{template-id} or +\grammarterm{splice-specialization-specifier}, +is considered nested for the purpose of this description. \end{footnote} is taken as the ending delimiter rather than a greater-than operator. Similarly, the first non-nested \tcode{>>} is treated as two consecutive but distinct \tcode{>} tokens, the first of which is taken as the end of the \grammarterm{template-argument-list} and completes -the \grammarterm{template-id}. +the \grammarterm{template-id} or \grammarterm{splice-specialization-specifier}. \begin{note} The second \tcode{>} token produced by this replacement rule can terminate an enclosing -\grammarterm{template-id} construct or it can be part of a different -construct (e.g., a cast). +\grammarterm{template-id} or \grammarterm{splice-specialization-specifier} +construct or it can be part of a different construct (e.g., a cast). \end{note} \begin{example} \begin{codeblock} @@ -809,6 +828,20 @@ The keyword \keyword{template} shall not appear immediately after a declarative \grammarterm{nested-name-specifier}\iref{expr.prim.id.qual}. +\pnum +The \grammarterm{constant-expression} of a \grammarterm{template-argument} +shall not be an unparenthesized \grammarterm{splice-expression}. +\begin{example} +\begin{codeblock} +template struct S { }; +constexpr int k = 5; +constexpr std::meta::info r = ^^k; +S<[:r:]> s1; // error: unparenthesized \grammarterm{splice-expression} used as template argument +S<([:r:])> s2; // OK +S<[:r:] + 1> s3; // OK +\end{codeblock} +\end{example} + \pnum A name prefixed by the keyword \keyword{template} @@ -854,7 +887,8 @@ \end{example} \pnum -A \grammarterm{template-id} is \defnx{valid}{\idxgram{template-id}!valid} if +A \grammarterm{template-id} or \grammarterm{splice-specialization-specifier} +is \defnx{valid}{\idxgram{template-id}!valid} if \begin{itemize} \item there are at most as many arguments as there are parameters @@ -873,11 +907,15 @@ template parameters (if any) succeeds, and \item - if the \grammarterm{template-id} is non-dependent, + if the \grammarterm{template-id} or + \grammarterm{splice-specialization-specifier} is non-dependent, the associated constraints are satisfied as specified in the next paragraph. \end{itemize} -A \grammarterm{simple-template-id} shall be valid unless it names a -function template specialization\iref{temp.deduct}. +A \grammarterm{simple-template-id} or +\grammarterm{splice-specialization-specifier} +shall be valid unless its respective +\grammarterm{template-name} or \grammarterm{splice-specifier} +names or designates a function template\iref{temp.deduct}. \begin{example} \begin{codeblock} template class X; @@ -894,13 +932,16 @@ \pnum When the \grammarterm{template-name} -of a \grammarterm{simple-template-id} -names a constrained non-function template +of a \grammarterm{simple-template-id} or +the \grammarterm{splice-specifier} +of a \grammarterm{splice-specialization-specifier} +designates a constrained non-function template or a constrained template template parameter, and all \grammarterm{template-argument}{s} -in the \grammarterm{simple-template-id} +in the \grammarterm{simple-template-id} or +\grammarterm{splice-specialization-specifier} are non-dependent\iref{temp.dep.temp}, the associated constraints\iref{temp.constr.decl} of the constrained template @@ -966,10 +1007,9 @@ \pnum \indextext{argument!template}% -The type and form of each -\grammarterm{template-argument} -specified in a -\grammarterm{template-id} +The type and form of each \grammarterm{template-argument} specified +in a \grammarterm{template-id} or +in a \grammarterm{splice-specialization-specifier} shall match the type and form specified for the corresponding parameter declared by the template in its \grammarterm{template-parameter-list}. @@ -1135,7 +1175,9 @@ \end{note} \pnum -When a \grammarterm{simple-template-id} does not name a function, +When a \grammarterm{simple-template-id} or +\grammarterm{splice-specialization-specifier} +does not designate a function, a default \grammarterm{template-argument} is implicitly instantiated\iref{temp.inst} when the value of that default argument is needed. @@ -2442,6 +2484,10 @@ \item they are of type \tcode{std::nullptr_t}, or +\item +they are of type \tcode{std::meta::info} and +their values compare equal\iref{expr.eq}, or + \item they are of enumeration type and their values are the same, \begin{footnote} @@ -2777,8 +2823,8 @@ \pnum Deduction guides are used -when a \grammarterm{template-name} appears -as a type specifier +when a \grammarterm{template-name} or \grammarterm{splice-type-specifier} +appears as a type specifier for a deduced class type\iref{dcl.type.class.deduct}. Deduction guides are not found by name lookup. Instead, when performing class template argument deduction\iref{over.match.class.deduct}, @@ -3005,7 +3051,7 @@ \begin{note} A specialization of a conversion function template -is referenced in +is named in the same way as a non-template conversion function that converts to the same type\iref{class.conv.fct}. \begin{example} @@ -3024,9 +3070,12 @@ } \end{codeblock} \end{example} -There is no syntax to form a \grammarterm{template-id}\iref{temp.names} -by providing an explicit template argument list\iref{temp.arg.explicit} -for a conversion function template. +An expression designating +a particular specialization of a conversion function template +can only be formed with a \grammarterm{splice-expression}. +There is no analogous syntax to form a \grammarterm{template-id}\iref{temp.names} +for such a function +by providing an explicit template argument list\iref{temp.arg.explicit}. \end{note} \rSec2[temp.variadic]{Variadic templates} @@ -4553,11 +4602,22 @@ types. The name of the alias template is a \grammarterm{template-name}. \pnum -When a \grammarterm{template-id} refers to the specialization of -an alias template, it is equivalent to the associated type obtained by +A +\begin{itemize} +\item +\grammarterm{template-id} +that is not the operand of a \grammarterm{reflect-expression} or +\item +\grammarterm{splice-specialization-specifier} +\end{itemize} +that designates the specialization of +an alias template is equivalent to the associated type obtained by substitution of its \grammarterm{template-argument}{s} for the \grammarterm{template-parameter}{s} in the \grammarterm{defining-type-id} of the alias template. +Any other \grammarterm{template-id} +that names a specialization of an alias template is +a \grammarterm{typedef-name} for a type alias. \begin{note} An alias template name is never deduced. \end{note} @@ -4831,7 +4891,9 @@ \grammarterm{type-requirement}, \grammarterm{nested-name-specifier}, \grammarterm{elaborated-type-specifier}, -\grammarterm{class-or-decltype}, or +\grammarterm{class-or-decltype}, +\grammarterm{using-enum-declarator}, +or \item a \grammarterm{simple-type-specifier} of a \grammarterm{friend-type-specifier}, or \item @@ -4869,17 +4931,26 @@ (which necessarily declares a constant template parameter). \end{itemize} \end{itemize} +A \grammarterm{splice-specifier} or +\grammarterm{splice-specialization-specifier}\iref{basic.splice} +is said to be in a type-only context +if a hypothetical qualified name appearing in the same position +would be in a type-only context. \begin{example} \begin{codeblock} template T::R f(); // OK, return type of a function declaration at global scope template void f(T::R); // ill-formed, no diagnostic required: attempt to declare // a \keyword{void} variable template +enum class Enum { A, B, C }; template struct S { using Ptr = PtrTraits::Ptr; // OK, in a \grammarterm{defining-type-id} + using Alias = [:^^int:]; // OK, in a \grammarterm{defining-type-id} T::R f(T::P p) { // OK, class scope return static_cast(p); // OK, \grammarterm{type-id} of a \keyword{static_cast} } auto g() -> S::Ptr; // OK, \grammarterm{trailing-return-type} + auto h() -> [:^^S:]; // OK, \grammarterm{trailing-return-type} + using enum [:^^Enum:]; // OK, \grammarterm{using-enum-declarator} }; template void f() { void (*pf)(T::X); // variable \tcode{pf} of type \tcode{\keyword{void}*} initialized with \tcode{T::X} @@ -5573,6 +5644,10 @@ \item a \grammarterm{pack-index-specifier}, or \item denoted by \tcode{decltype(}\grammarterm{expression}{}\tcode{)}, where \grammarterm{expression} is type-dependent\iref{temp.dep.expr}. +\item denoted by a \grammarterm{splice-type-specifier} in which either +the \grammarterm{splice-specifier} or +\grammarterm{splice-specialization-specifier} +is dependent\iref{temp.dep.splice}. \end{itemize} \pnum @@ -5702,7 +5777,8 @@ \opt{\terminal{::}} \keyword{delete} \terminal{[} \terminal{]} cast-expression\br \keyword{throw} \opt{assignment-expression}\br \keyword{noexcept} \terminal{(} expression \terminal{)}\br -requires-expression +requires-expression\br +reflect-expression \end{ncsimplebnf} \begin{note} @@ -5748,6 +5824,12 @@ A \grammarterm{pack-index-expression} is type-dependent if its \grammarterm{id-expression} is type-dependent. +\pnum +A \grammarterm{splice-expression} is type-dependent +if its \grammarterm{splice-specifier} or +\grammarterm{splice-specialization-specifier} +is dependent\iref{temp.dep.splice}. + \rSec3[temp.dep.constexpr]{Value-dependent expressions} \pnum @@ -5850,6 +5932,107 @@ the result of the evaluation refers to a templated entity that is an object with static or thread storage duration or a member function. +\pnum +A \grammarterm{reflect-expression} is value-dependent if +\begin{itemize} +\item +it is of the form \tcode{\caret\caret \grammarterm{reflection-name}} and +the \grammarterm{reflection-name} +\begin{itemize} +\item is a dependent qualified name, +\item is a dependent \grammarterm{namespace-name}, +\item is the name of a template parameter, or +\item names a dependent member of the current instantiation\iref{temp.dep.type}, +\end{itemize} +\item +it is of the form \tcode{\caret\caret \grammarterm{type-id}} and +the \grammarterm{type-id} denotes a dependent type, or +\item +it is of the form \tcode{\caret\caret \grammarterm{id-expression}} and +the \grammarterm{id-expression} is value-dependent. +\end{itemize} + +\pnum +A \grammarterm{splice-expression} is value-dependent +if its \grammarterm{splice-specifier} or +\grammarterm{splice-specialization-specifier} +is dependent\iref{temp.dep.splice}. + +\rSec3[temp.dep.splice]{Dependent splice specifiers} + +\pnum +A \grammarterm{splice-specifier} is dependent +if its converted \grammarterm{constant-expression} is value-dependent. +A \grammarterm{splice-specialization-specifier} is dependent +if its \grammarterm{splice-specifier} is dependent or +if any of its template arguments are dependent. +A \grammarterm{splice-scope-specifier} is dependent +if its \grammarterm{splice-specifier} or +\grammarterm{splice-specialization-specifier} is dependent. + +\pnum +\begin{example} +\begin{codeblock} +template +void fn() { + using a = [:T:]<1>; // \tcode{[:T:]<1>} is dependent because \tcode{[:T:]} is dependent + static_assert([:NS:]::template TCls<1>::v == a::v); // \tcode{[:NS:]} is dependent +} + +namespace N { + template struct TCls { static constexpr int v = V; }; +} + +int main() { + fn<^^N::TCls, ^^N>(); +} +\end{codeblock} +\end{example} + +\pnum +\begin{example} +\begin{codeblock} +template class X> +struct S { + [:^^X:] m; +}; + +template struct V1 {}; +template struct V2 {}; + +S s1; // error: \tcode{V1} has too many template arguments +S s2; // OK +\end{codeblock} +\end{example} + +\rSec3[temp.dep.namespace]{Dependent namespaces} + +\pnum +A namespace alias is dependent +if it is introduced by a \grammarterm{namespace-alias-definition} +whose \grammarterm{qualified-namespace-specifier} (if any) is +a dependent qualified name or +whose \grammarterm{splice-specifier} (if any) is dependent. +A \grammarterm{namespace-name} is dependent +if it names a dependent namespace alias. + +\pnum +\begin{example} +\begin{codeblock} +template +int fn() { + namespace Alias = [:R:]; // \tcode{[:R:]} is dependent + return typename Alias::T{}; // \tcode{Alias} is dependent +} + +namespace NS { + using T = int; +} + +int a = fn<^^NS>(); +\end{codeblock} +\end{example} + \rSec3[temp.dep.temp]{Dependent template arguments} \pnum @@ -7134,11 +7317,10 @@ or to make it compile will be such a trial as to kindle its self-immolation. \pnum -A -\grammarterm{simple-template-id} -that names a class template explicit specialization that has been declared but -not defined can be used exactly like the names of other incompletely-defined -classes\iref{basic.types}. +\begin{note} +A class template explicit specialization that has been declared but +not defined can be used exactly like other +incompletely-defined classes\iref{basic.types}. \begin{example} \begin{codeblock} template class X; // \tcode{X} is a class template @@ -7148,6 +7330,7 @@ X x; // error: object of incomplete class \tcode{X} \end{codeblock} \end{example} +\end{note} \pnum \begin{note} @@ -7567,7 +7750,8 @@ \pnum When an explicit template argument list is specified, if the -given \grammarterm{template-id} is not valid\iref{temp.names}, +given \grammarterm{template-id} or +\grammarterm{splice-specialization-specifier} is not valid\iref{temp.names}, type deduction fails. Otherwise, the specified template argument values are substituted for the corresponding template parameters as specified below. @@ -8158,7 +8342,8 @@ is a class and \tcode{P} has the form -\grammarterm{simple-template-id}, +\grammarterm{simple-template-id} or +\opt{\keyword{typename}} \grammarterm{splice-specialization-specifier}, then the transformed \tcode{A} can be a derived class \tcode{D} of the @@ -8167,7 +8352,8 @@ Likewise, if \tcode{P} is a pointer to a class of the form -\grammarterm{simple-template-id}, +\grammarterm{simple-template-id} or +\opt{\keyword{typename}} \grammarterm{splice-specialization-specifier}, the transformed \tcode{A} can be a pointer to a derived class \tcode{D} pointed to by the deduced @@ -8702,6 +8888,8 @@ \item The \grammarterm{expression} of a \grammarterm{decltype-specifier}. \item +The \grammarterm{constant-expression} of a \grammarterm{splice-specifier}. +\item A constant template argument or an array bound in which a subexpression references a template parameter. \item @@ -9175,8 +9363,8 @@ If \tcode{P} has a form that contains \tcode{}, and if the type of \tcode{i} differs from the type of the corresponding template parameter -of the template named by the enclosing \grammarterm{simple-template-id}, -deduction fails. +of the template named by the enclosing \grammarterm{simple-template-id} or +\grammarterm{splice-specialization-specifier}, deduction fails. If \tcode{P} has a form that contains \tcode{[i]}, and if the type of \tcode{i} is not an integral type, deduction fails. \begin{footnote}