Document: | PL22.16/11-0032 = WG21 N3262 |
Author: | William M. (Mike) Miller Edison Design Group, Inc. |
Date: | 2011-03-25 |
The following issue resolutions, in addition to those in "ready" and "tentatively ready" status in document PL22.16/11-0006 = N3236, have been approved by the Core Language Working Group to be applied to the FDIS.
531. Defining members of explicit specializations
Proposed resolution:
Change 14.7.3 paragraphs 4-6 as follows:
A member function, a member function template, a member class, a member class template, or a static data member of a class template may be explicitly specialized for a class specialization that is implicitly instantiated; in this case, the definition of the class template shall precede the explicit specialization...
A member of an explicitly specialized class is not implicitly instantiated from the member declaration of the class template; instead, the member of the class template specialization shall itself be explicitly defined if its definition is required. In this case, the definition of the class template explicit specialization shall be in scope at the point
of declaration of the explicit specialization ofat which the member is defined. The definition of an explicitly specialized class...Definitions of membersMembers of an explicitly specialized class template are defined in the same manner as members of normal classes, and not using the template<> syntaxfor explicit specialization. The same is true when defining a member of an explicitly specialized member class. However, template<> is used in defining a member of an explicitly specialized member class template that is specialized as a class template. [Example:template<class T> struct A {void f(T) { /* ... */ }struct B { }; template<class U> struct C { }; }; template<> struct A<int> { void f(int); }; void h() { A<int> a; a.f(16); // A<int>::f must be defined somewhere } //explicit specialization syntaxtemplate<> not used for a member of an // explicitly specialized class templatespecializationvoid A<int>::f(int) { /* ... */ } template<> struct A<char>::B { void f(); }; // template<> also not used when defining a member of // an explicitly-specialized member class void A<char>::B::f() { /* ... */ } template<> template<class U> struct A<char>::C { void f(); }; // template<> is used when defining a member of an explicitly // specialized member class template specialized as a class template template<> template<class U> void A<char>::C<U>::f() { /* ... */ } template<> struct A<short>::B { void f(); }; template<> void A<short>::B::f() { /* ... */ } // error: template<> not permitted template<> template<class U> struct A<short>::C { void f(); }; template<class U> void A<short>::C<U>::f() { /* ... */ } // error: requires template<>—end example]
If a template, a member template or
thea member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place...
547. Partial specialization on member function types
Proposed resolution:
Change 8.3.5 paragraph 6 as follows:
A cv-qualifier-seq or a ref-qualifier shall only be part of:[Drafting note: this resolution transforms the running text of the first sentence of 8.3.5 paragraph 6 into a bulleted list.]
the function type for a non-static member function,
the function type to which a pointer to member refers,
orthe top-level function type of a function typedef declaration.or alias-declaration,the type-id in the default argument of a type-parameter (14.1 [temp.param]), or
the type-id of a template-argument for a type-parameter (14.2 [temp.names]).
[Note: A function type that has a cv-qualifier-seq is not a cv-qualified type; there are no cv-qualified function types. —end note]The effect of a cv-qualifier-seq in a function declarator is not the same as adding cv-qualification on top of the function type. In the latter case, the cv-qualifiers are ignored. [Note: A function type that has a cv-qualifier-seq is not a cv-qualified type; there are no cv-qualified function types. —end note] [Example:... —end example]A ref-qualifier shall only be part of the function type for a non-static member function, the function type to which a pointer to member refers, or the top-level function type of a function typedef declaration.The return type...
580. Access in template-parameters of member and friend definitions
Proposed resolution:
Change 11 [class.access] paragraphs 6-7 as follows:
All access controls in Clause 11 [class.access] affect the ability to access a class member name from the declaration of a particular
scopeentity, including parts of the declaration preceding the name of the entity being declared and, if the entity is a class, the definitions of members of the class appearing outside the class's member-specification. [Note: this access also applies to implicit references to constructors, conversion functions, and destructors. —end note]For purposes of access control, the base-specifiers of a class and the definitions of class members that appear outside of the class definition are considered to be within the scope of that class. In particular, access controls apply as usual to member names accessed as part of a function return type, even though it is not possible to determine the access privileges of that use without first parsing the rest of the function declarator. Similarly, access control for implicit calls to the constructors, the conversion functions, or the destructor called to create and destroy a static data member is performed as if these calls appeared in the scope of the member's class.[Example:class A { typedef int I; // private member I f(); friend I g(I); static I x; template<int> struct Q; template<int> friend struct R; protected: struct B { }; }; A::I A::f() { return 0; } A::I g(A::I p = A::x); A::I g(A::I p) { return 0; } A::I A::x = 0; template<A::I> struct A::Q { }; template<A::I> struct R { }; struct D: A::B, A { };
Here, all the uses of A::I are well-formed because A::f
and, A::x, and A::Q are members of class A and gis a friendand R are friends of class A. This implies, for example, that access checking on the first use of A::I must be deferred until it is determined that this use of A::I is as the return type of a member of class A. Similarly, the use of A::B as a base-specifier is well-formed because D is derived from A, so checking of base-specifiers must be deferred until the entire base-specifier-list has been seen. —end example]
758. Missing cases of declarations that are not definitions
Proposed Resolution:
Change 3.1 [basic.def] paragraph 2 as follows:
A declaration is a definition unless it declares a function without specifying the function's body (8.4 [dcl.fct.def]), it contains the extern specifier (7.1.1 [dcl.stc]) or a linkage-specification25 (7.5 [dcl.link]) and neither an initializer nor a function-body, it declares a static data member in a class definition (9.2 [class.mem], 9.4 [class.static]), it is a class name declaration (9.1 [class.name]), it is an opaque-enum-declaration (7.2 [dcl.enum]), it is a template-parameter (14.1 [temp.param]), it is a parameter-declaration (8.3.5 [dcl.fct]) in a function declarator that is not the declarator of a function-definition, or it is a typedef declaration (7.1.3 [dcl.typedef]), an alias-declaration (7.1.3 [dcl.typedef]), a using-declaration (7.3.3 [namespace.udecl]), a static_assert-declaration (Clause 7 [dcl.dcl]), an attribute-declaration (Clause 7 [dcl.dcl]), an empty-declaration (Clause 7 [dcl.dcl]), or a using-directive (7.3.4 [namespace.udir]).
798. Overloaded subscript operator described in clause 5
Proposed resolution:
Change 5.2.1 [expr.sub] paragraph 2 as follows:
A braced-init-list
may appear as a subscript for a user-defined operator[]. In that case, the initializer list is treated as the initializer for the subscript argument of the operator[]. An initializer listshall not be used with the built-in subscript operator.
[Example:struct X { Z operator[](std::initializer_list<int>); }; X x; x[{1,2,3}] = 7; // OK: meaning x.operator[]({1,2,3}) int a[10]; a[{1,2,3}] = 7; // error: built-in subscript operator
—end example]
Change 13.5.5 [over.sub] paragraph 1 as follows:
operator[] shall be a non-static member function with exactly one parameter. It implements the subscripting syntax
posfix-expression [ expression ]
or
postfix-expression [ braced-init-list ]
Thus, a subscripting expression x[y] is interpreted as x.operator[](y) for a class object x of type T if T::operator[](T1) exists and if the operator is selected as the best match function by the overload resolution mechanism (13.3.3 [over.match.best]). [Example:
struct X { Z operator[](std::initializer_list<int>); }; X x; x[{1,2,3}] = 7; // OK: meaning x.operator[]({1,2,3}) int a[10]; a[{1,2,3}] = 7; // error: built-in subscript operator—end example]
996. Ambiguous partial specializations of member class templates
Proposed resolution:
Change 14.7.1 [temp.local] paragraph 1 as follows, creating a new paragraph from the existing text following the new example:
Unless a class template specialization has been explicitly instantiated (14.7.2 [temp.explicit]) or explicitly specialized (14.7.3 [temp.expl.spec]), the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program. The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions or default arguments, of the class member functions, member classes, static data members and member templates; and it causes the implicit instantiation of the definitions of member anonymous unions. However, for the purpose of determining whether an instantiated redeclaration of a member is valid according to 9.2 [class.mem], a declaration that corresponds to a definition in the template is considered to be a definition. [Example:
template<typename T, typename U> struct Outer { template<typename X, typename Y> struct Inner; template<typename Y> struct Inner<T, Y>; // #1a template<typename Y> struct Inner<T, Y> {}; // #1b: Ok; valid redeclaration of #1a template<typename Y> struct Inner<U, Y> {}; // #2 }; Outer<int, int> outer; // Error at #2.Outer<int,int>::Inner<int,Y> is redeclared at #1b. (It is not defined but noted as being associated with a definition in Outer<T,U>.) #2 is also a redeclaration of #1a. It is also noted as associated with a definition, so it is an invalid redeclaration of the same partial specialization. —end example]
Unless a member of a class template or a member template has been explicitly instantiated...
997. Argument-dependent lookup and dependent function template parameter types
Proposed resolution
Change 3.4.2 [basic.lookup.argdep] paragraph 2 as follows:
...In addition, if the argument is the name or address of a set of overloaded functions and/or function templates, its associated classes and namespaces are the union of those associated with each of the members of the set, i.e., the classes and namespaces associated with its(non-dependent)parameter types and return type. Additionally, if the aforementioned set of overloaded functions is named with a template-id, its associated classes and namespaces also include those of its type template-arguments and its template template-arguments.
(This resolution also resolves issue 1015.)
1004. Injected-class-names as arguments for template template parameters
Proposed resolution:
Change 14.6.1 [temp.local] paragraphs 1-5 as follows:
Like normal (non-template) classes, class templates have an injected-class-name (Clause 9 [class]). The injected-class-name can be used
with or without a template-argument-listas a template-name or a type-name.When it is used without a template-argument-list, it is equivalent to the injected-class-name followed by the template-parameters of the class template enclosed in <>.When it is used with a template-argument-list, as a template-argument for a template template-parameter, or as the final identifier in the elaborated-type-specifier of a friend class template declaration, it refers to thespecified class template specialization, which could be the current specialization or another specialization.class template itself. Otherwise, it is equivalent to the template-name followed by the template-parameters of the class template enclosed in <>.Within the scope of a class template specialization or partial specialization, when the injected-class-name is
not followed by a <used as a type-name, it is equivalent to theinjected-class-nametemplate-name followed by the template-arguments of the class template specialization or partial specialization enclosed in <>. [Example:template<template<class> class T> class A { }; template<class T> class Y; template<> class Y<int> { Y* p; // meaning Y<int> Y<char>* q; // meaning Y<char> A<Y>* a; // meaning A<::Y> class B { template<class> friend class Y; // meaning ::Y }; };—end example]
The injected-class-name of a class template or class template specialization can be used either
with or without a template-argument-listas a template-name or a type-name wherever it is in scope. [Example:template <class T> struct Base { Base* p; }; template <class T> struct Derived: public Base<T> { typename Derived::Base* p; // meaning Derived::Base<T> }; template<class T, template<class> class U = T::template Base> struct Third { }; Third<Base<int>> t; // OK, default argument uses injected-class-name as a template—end example]
A lookup that finds an injected-class-name (10.2 [class.member.lookup]) can result in an ambiguity in certain cases (for example, if it is found in more than one base class). If all of the injected-class-names that are found refer to specializations of the same class template, and if the name is
followed by a template-argument-listused as a template-name, the reference refers to the class template itself and not a specialization thereof, and is not ambiguous. [Example:template <class T> struct Base { }; template <class T> struct Derived: Base<int>, Base<char> { typename Derived::Base b; // error: ambiguous typename Derived::Base<double> d; // OK };—end example]
When the normal name of the template (i.e., the name from the enclosing scope, not the injected-class-name) is used
without a template-argument-list, it always refers to the class template itself and not a specialization of the template. [Example:...
(This resolution also resolves issue 602).
1018. Ambiguity between simple-declaration and attribute-declaration
Proposed resolution:
Change 7 [dcl.dcl] paragraph 1 as follows:
...Theoptionalattribute-specifier-seq in a simple-declaration appertains to each of the entities declared by the declarators; it shall not appear if the optionalof the init-declarator-listis omitted...
1031. Optional elements in attributes
Proposed resolution:
Change the grammar of 7.6.1 [dcl.attr.grammar] paragraph 1 as follows:
1032. Empty pack expansions
Proposed resolution:
Change 14.5.3 [temp.variadic] paragraph 6 as follows:
...All of the Ei become elements in the enclosing list. [Note: The variety of list varies with the context: expression-list, base-specifier-list, template-argument-list, etc. —end note] When N is zero, the instantiation of the expansion produces an empty list. Such an instantiation does not alter the syntactic interpretation of the enclosing construct, even in cases where omitting the list entirely would otherwise be ill-formed or would result in an ambiguity in the grammar. [Example:
template<typename ...T> struct X : T... { }; template<typename ...T> void f(T ...values) { X<T...> x(values...); } template void f<>(); // okay: X<> has no base classes // x is a variable of type X<> that is value-initialized—end example]
1033. Restrictions on alignment attributes
Proposed resolution:
Change 7.6.2 [dcl.align] paragraph 5 as follows:
The combined effect of all alignment-specifiers in a declaration shall not specify an alignment that is less strict than the alignment that wouldotherwisebe required for the entity being declared if all alignment-specifiers were omitted (including those in other declarations).
1035. Omitted and required decl-specifiers
Proposed resolution:
Change 9.2 [class.mem] paragraph 7 as follows:
The decl-specifier-seqismay be omitted in constructor, destructor, and conversion function declarations only; when declaring another kind of member the decl-specifier-seq shall contain a type-specifier that is not a cv-qualifier. The member-declarator-list can be omitted...
Change C.1.5 [diff.dcl], “Banning implicit int,” as follows:
In C++ a decl-specifier-seq must contain a type-specifier, unless it is followed by a declarator for a constructor, a destructor, or a conversion function. In the following example...
1042. Attributes in alias-declarations
Proposed resolution:
Change the grammar in 7 [dcl.dcl] paragraph 1 as follows:
Change 7.1.3 [dcl.typedef] paragraph 2 as follows:
A typedef-name can also be introduced by an alias-declaration. The identifier following the using keyword becomes a typedef-name and the optional attribute-specifier-seq following the identifier appertains to that typedef-name. It has the same semantics...
1055. Permissible uses of void
Proposed resolution:
Change 3.9.1 [basic.fundamental] paragraph 9 as follows:
...Any expression can be explicitly converted to type cv void (5.4 [expr.cast]). An expression of type void shall be used only as an expression statement (6.2 [stmt.expr]), as an operand of a comma expression (5.18 [expr.comma]), as a second or third operand of ?: (5.16 [expr.cond]), as the operand of typeid or decltype,oras the expression in a return statement (6.6.3 [stmt.return]) for a function with the return type void, or as the operand of an explicit conversion to type cv void.
Change 5.16 [expr.cond] paragraph 2 as follows:
If either the second or the third operand has type(possibly cv-qualified)void, then...
Change 6.6.3 [stmt.return] paragraph 3 as follows:
A return statement with an expression of type“cvvoid”can be used only in functions with a return type of cv void; the expression is evaluated just before the function returns to its caller.
1056. Template aliases, member definitions, and the current instantiation
Proposed resolution:
Change 14.6.2.1 [temp.dep.type] paragraph 1 as follows:
In the definition of a class template, a nested class of a class template, a member of a class template, or a member of a nested class of a class template, a name refers to the current instantiation if it is
the injected-class-name (Clause [class]) of the class template or nested class,
in the definition of a primary class template, the name of the class template followed by the template argument list of the primary template (as described below) enclosed in <> (or an equivalent template alias specialization),
in the definition of a nested class of a class template, the name of the nested class referenced as a member of the current instantiation, or
in the definition of a partial specialization, the name of the class template followed by the template argument list of the partial specialization enclosed in <> (or an equivalent template alias specialization). If the nth template parameter is a parameter pack, the nth template argument is a pack expansion (14.5.3 [temp.variadic]) whose pattern is the name of the parameter pack.
1057. decltype and the current instantiation
Proposed resolution:
Add the following as a new paragraph following 14.4 [temp.type] paragraph 1:
If an expression e involves a template parameter, decltype(e) denotes a unique dependent type. Two such decltype-specifiers refer to the same type only if their expressions are equivalent (14.5.6.1 [temp.over.link]). [Note: However, it may be aliased, e.g., by a typedef-name —end note].
1074. Value-dependent noexcept-expressions
Proposed resolution:
Delete “noexcept( expression )” from the list in 14.6.2.3 [temp.dep.constexpr] paragraph 3.
1079. Overload resolution involving aggregate initialization
Proposed resolution:
Change 13.3.3.2 [over.ics.rank] paragraph 3 bullet 2 as follows:
User-defined conversion sequence U1 is a better conversion sequence than another user-defined conversion sequence U2 if they contain the same user-defined conversion function or constructor or aggregate initialization, and if the second standard conversion sequence of U1 is better than the second standard conversion sequence of U2.
1082. Implicit copy function if subobject has none?
Proposed resolution:
Change 12.8 [class.copy] paragraph 8 as follows:
If the class definition does not explicitly declare a copy constructor,there is no user-declared move constructor, and there is no user-declared move assignment operator, a copy constructor is implicitly declared as defaulted (8.4.2 [dcl.fct.def.default])one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted (8.4 [dcl.fct.def]).Such an implicit declarationThe latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor. Thus, for the class definition...
Change 12.8 [class.copy] paragraph 19 as follows:
If the class definition does not explicitly declare a copy assignment operator,there is no user-declared move constructor, and there is no user-declared move assignment operator, a copy assignment operator is implicitly declared as defaulted (8.4.2 [dcl.fct.def.default])one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy assignment operator is defined as deleted; otherwise, it is defined as defaulted (8.4 [dcl.fct.def]).Such implicit declarationThe latter case is deprecated if the class has a user-declared copy constructor or a user-declared destructor. The implicitly-declared copy assignment operator for a class X will have the form...
Change D.3 [depr.impldec] paragraph 1 as follows:
The implicitdeclarationdefinition of a copy constructor as defaulted is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor. The implicitdeclarationdefinition of a copy assignment operator as defaulted is deprecated if the class has a user-declared copy constructor or a user-declared destructor (12.4 [class.dtor], 12.8 [class.copy]). In a future revision of the Standard, these implicit definitions could become deleted (8.4 [dcl.fct.def]).
1088. Dependent non-type template arguments
Proposed resolution:
Add a new paragraph at the end of 14.6.2.3 [temp.dep.constexpr]:
An id-expression is value-dependent if it names a member of an unknown specialization.
Change 14.6.2.4 [temp.dep.temp] paragraphs 2-3 as follows:
An integralA non-type template-argument is dependent if its type is dependent or the constant expression it specifies is value-dependent.
A non-integralFurthermore, a non-type template-argument is dependent ifits type is dependent or it has either of the following forms
qualified-id
& qualified-id
and contains a nested-name-specifier which specifies a class-name that names a dependent typethe corresponding non-type template-parameter is of reference or pointer type and the template-argument designates or points to a member of the current instantiation or a member of a dependent type.
1090. Alignment of subobjects
Proposed resolution:
Change 3.11 [basic.align] paragraph 2 as follows:
A fundamental alignment is represented by an alignment less than or equal to the greatest alignment supported by the implementation in all contexts, which is equal to alignof(std::max_align_t) (18.2 [support.types]). The alignment required for a type might be different when it is used as the type of a complete object and when it is used as the type of a subobject. [Example:struct B { long double d; }; struct D: virtual B { char c; };When D is the type of a complete object, it will have a subobject of type B, so it must be aligned appropriately for a long double. If D appears as a subobject of another object that also has B as a virtual base class, the B subobject might be part of a different subobject, reducing the alignment requirement on the D subobject. —end example] The result of the alignof operator reflects the alignment requirement of the type in the complete-object case.
1095. List-initialization of references
Proposed resolution:
Change 8.5 [dcl.init] paragraph 16 bullet 1 as follows:
If the initializer is a braced-init-list, the object or reference is list-initialized (8.5.4 [dcl.init.list]).
Change 8.5.4 [dcl.init.list] paragraph 3 bullet 7 as follows:
Otherwise, if the initializer list has a single element, the object or reference is initialized from that element; if a narrowing conversion (see below) is required to convert the element to T, the program is ill-formed.
1101. Non-integral initialized static data members
Proposed resolution:
Change 9.4.2 [class.static.data] paragraph 3 as follows:
If a non-volatile const static data member is ofconst literalintegral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression (5.19 [expr.const]). A static data member of literal type can be declared in the class definition with the constexpr specifier...
1166. exception-declarations that do not declare objects
Proposed resolution:
Change 15.3 [except.handle] paragraph 1 as follows:
The exception-declaration in a handler describes the type(s) of exceptions that can cause that handler to be entered. The exception-declaration shall not denote an incomplete type, an abstract class type, or an rvalue reference type. The exception-declaration shall not denote a pointer or reference to an incomplete type, other than void*, const void*, volatile void*, or const volatile void*.
Change 15.3 [except.handle] paragraph 16 as follows:
The object declared in an exception-declaration or, if the exception-declarationIf the exception-declaration specifies a name, it declares a variable which is copy-initialized (8.5 [dcl.init]) from the exception object. If the exception-declaration denotes an object type, but does not specify a name, a temporary (12.2 [class.temporary]) is copy-initialized (8.5 [class.temporary]) from the exception object.The object shall not have an abstract class type.Theobject is destroyedlifetime of the variable or temporary ends when the handler exits, after the destruction of any automatic objects initialized within the handler.
1174. When is a pure virtual function “used?”
Proposed resolution (November, 2010):
Change 3.2 [basic.def.odr] paragraph 2 as follows:
...A variableor non-overloaded functionwhose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression (5.19 [expr.const]) and the lvalue-to-rvalue conversion (4.1 [conv.lval]) is immediately applied... A virtual member function is odr-used if it is not pure. A non-overloaded function whose name appears as a potentially-evaluated expression or a member of a set of candidate functionsis odr-usedifit isselected by overload resolution when referred to from a potentially-evaluated expression, are odr-used, unless it is a pure virtual function and its name is not explicitly qualified. [Note:...
1175. Disambiguating user-defined literals
Proposed resolution:
Change 2.14.8 [lex.ext] paragraph 1 as follows:
If a token matches both user-defined-literal and another literal kind, it is treated as the latter. [Example: 123_km, 1.2LL, "Hello"s are all user-defined-literals, but 12LL is an integer-literal. —end example] The syntactic nonterminal preceding the ud-suffix in a user-defined-literal is taken to be the longest sequence of characters that could match that nonterminal.
1178. Deduction failure matching placement new
Proposed resolution:
Change 14.8.2.6 [temp.deduct.decl] paragraphs 1-2 as follows:
In a declaration whose declarator-id refers to a specialization of a function template, template argument deduction is performed to identify the specialization to which the declaration refers. Specifically, this is done for explicit instantiations (14.7.2 [temp.explicit]), explicit specializations (14.7.3 [temp.expl.spec]), and certain friend declarations (14.5.4 [temp.friend]). This is also done to determine whether a deallocation function template specialization matches a placement operator new (3.7.4.2 [basic.stc.dynamic.deallocation], 5.3.4 [expr.new]). In all these cases, P is the type of the function template being considered as a potential match and A is either the function type from the declaration or the type of the deallocation function that would match the placement operator new as described in 5.3.4 [expr.new]. The deduction is done as described in 14.8.2.5 [temp.deduct.type].
If, for the set of function templates so considered, there is either no match or more than one match after partial ordering has been considered (14.5.6.2 [temp.func.order]), deduction fails and, in the declaration cases, the
declarationprogram is ill-formed.
1180. Over-aligned class types
Proposed resolution:
Change 3.11 [basic.align] paragraph 3 as follows:
[Note: every over-aligned type is or contains a class typewith a non-static data member to which an extended alignment has been appliedto which extended alignment applies (possibly through a non-static data member). —end note]
1184. Argument conversions to nondeduced parameter types
Proposed resolution:
Change 14.8.2.1 [temp.deduct.call] paragraph 4 as follows:
In general, the deduction process attempts to find template argument values that will make the deduced A identical to A (after the type A is transformed as described above). However, there are three cases that allow a difference:
If the original P is a reference type...
The transformed A can be another pointer...
If P is a class...
[Note: as specified in 14.8.1 [temp.arg.explicit], implicit conversions will be performed on a function argument to convert it to the type of the corresponding function parameter if the parameter contains no template-parameters that participate in template argument deduction. Such conversions are also allowed, in addition to the ones described in the preceding list. —end note]
1185. Misleading description of language linkage and member function types
Proposed resolution:
Change 7.5 [dcl.link] paragraph 4 as follows:
...A C language linkage is ignoredforin determining the language linkage of the names of class members and thememberfunction type of class member functions...
1186. Non-dependent constexpr violations in function templates
Proposed resolution:
Change 7.1.5 [dcl.constexpr] paragraph 6 as follows:
If the instantiated template specialization of a constexpr function template or member function of a class template would fail to satisfy the requirements for a constexpr function or constexpr constructor, that specialization is not a constexpr function or constexpr constructor. [Note: if the function is a member function it will still be const as described below.Implementations are encouraged to issue a warning if a function is rendered not constexpr by a non-dependent construct.—end note] If no specialization of the template would yield a constexpr function or constexpr constructor, the program is ill-formed; no diagnostic required.
1188. Type punning in constant expressions
Proposed resolution:
Change 5.19 [expr.const] paragraph 2 as follows:
an lvalue-to-rvalue conversion...
an lvalue-to-rvalue conversion (4.1 [conv.lval]) that is applied to a glvalue that refers to a non-active member of a union or a subobject thereof;
...
a type conversion from a pointer or pointer-to-member type to a
literal type [Note: a user-defined conversion invokes a function
—end note] a reinterpret_cast
(5.2.10 [expr.reinterpret.cast]);
(This resolution also resolves issue 1098.)
1189. Address of distinct base class subobjects
Proposed resolution:
Change 1.8 [intro.object] paragraph 6 as follows:
Unless an object is a bit-field or a base class subobject of zero size, the address of that object is the address of the first byte it occupies. Twodistinctobjects that areneithernot bit-fieldsnor base class subobjects of zero size shall have distinct addressesmay have the same address if one is a subobject of the other, or if at least one is a base class subobject of zero size and they are of different types; otherwise, they shall have distinct addresses.4...
1190. Operations on non-safely-derived pointers
Proposed resolution:
Change 3.7.4.3 [basic.stc.dynamic.safety] paragraph 4 as follows:
...Alternatively, an implementation may have strict pointer safety, in which case, ifa pointer value that is not a safely-derived pointer value isdereferenced or deallocated, andan invalid pointer value, unless the referenced complete object is of dynamic storage duration and hasnotpreviously been declared reachable (20.9.10 [util.smartptr]), the behavior is undefined. [Note:thisThe effect of using an invalid pointer value (including passing it to a deallocation function) is undefined, see 3.7.4.2 [basic.stc.dynamic.deallocation]. This is true even if the unsafely-derived pointer value might compare equal to some safely-derived pointer value. —end note] It is implementation defined...
1192. Inadvertent change to ODR and templates
Proposed resolution
Change 3.2 [basic.def.odr] paragraph 5 as follows:
...If D is a template and is defined in more than one translation unit, then thelast fourpreceding requirementsfrom the list aboveshall apply both to names from the template's enclosing scope used in the template definition (14.6.3 [temp.nondep]), and also to dependent names at the point of instantiation (14.6.2 [temp.dep])...
1196. Definition required for explicit instantiation after explicit specialization?
Proposed resolution:
Change 14.7.2 [temp.explicit] paragraphs 3-4 as follows:
A declaration of a function template shall be in scope at the point of the explicit instantiation of the function template. A definition of the class or class template containing a member function template shall be in scope at the point of the explicit instantiation of the member function template. A definition of a class template or class member template shall be in scope at the point of the explicit instantiation of the class template or class member template. A definition of a class template shall be in scope at the point of an explicit instantiation of a member function or a static data member of the class template. A definition of a member class of a class template shall be in scope at the point of an explicit instantiation of the member class.A declaration of a function template, a member function or static data member of a class template, or a member function template of a class or class template shall precede an explicit instantiation of that entity. A definition of a class template, a member class of a class template, or a member class template of a class or class template shall precede an explicit instantiation of that entity, unless the explicit instantiation is preceded by an explicit specialization of the entity with the same template arguments. If the declaration of the explicit instantiation names an implicitly-declared special member function (Clause 12 [special]), the program is ill-formed.For a given set of template
parametersarguments, if an explicit instantiation of a template appears after a declaration of an explicit specialization for that template, the explicit instantiation has no effect. Otherwise...
1202. Calling virtual functions during destruction
Proposed resolution:
Change 12.7 [class.cdtor] paragraph 4 as follows:
Member functions, including virtual functions (10.3 [class.virtual]), can be called during construction or destruction (12.6.2 [class.base.init]). When a virtual function is called directly or indirectly from a constructor(including the mem-initializer or brace-or-equal-initializer for a non-static data member)or from a destructor, including during the construction or destruction of the class's non-static data members, and the object to which the call applies is the object (call it x) under construction or destruction, the function called is theone defined in the constructor or destructor's own class or in one of its bases, but not a function overriding it in a class derived from the constructor or destructor's class, or overriding it in one of the other base classes of the most derived object (1.8 [intro.object])final overrider in the constructor or destructor's class and not one overriding it in a more-derived class. If the virtual function call uses an explicit class member access (5.2.5 [expr.ref]) and the object-expression refers tothe object under construction or destruction but its type is neither the constructor or destructor's own class or one of its bases, the result of the callthe complete object of x or one of that object's base class subobjects but not x or one of its base class subobjects, the behavior is undefined. [Example:...
1204. Specifiers in a for-range-declaration
Proposed resolution:
Change the grammar 6.5 [stmt.iter] paragraph 1 as follows:
Add the following as a new paragraph at the end of 6.5.4 [stmt.ranged]:
In the decl-specifier-seq of a for-range-declaration, each decl-specifier shall be either a type-specifier or constexpr.
1206. Defining opaque enumeration members of class templates
Proposed resolution:
Change 14 [temp] paragraph 1 as follows:
...The declaration in a template-declaration shall
declare or define a function or class, or
define a member function, a member class, a member enumeration, or a static data member of a class template or of a class nested within a class template, or
...
Change 14.5.1 [temp.class] paragraph 3 as follows:
When a member function, a member class, a member enumeration, a static data member or a member template of a class template is defined outside of the class template definition...
Add a new section following 14.5.1.3 [temp.static]:
14.5.1.4 Enumeration members of class templates [temp.mem.enum]
An enumeration member of a class template may be defined outside the class template definition. [Example:
template<class T> struct A { enum E: T; }; A<int> a; template<class T> enum A<T>::E: T { e1, e2 }; A<int>::E e = A<int>::e1;—end example]
Change 14.7 [temp.spec] paragraph 2 as follows:
A function instantiated from a function template is called an instantiated function. A class instantiated from a class template is called an instantiated class. A member function, a member class, a member enumeration, or a static data member of a class template instantiated from the member definition of the class template is called, respectively, an instantiated member function, member class, member enumeration, or static data member. A member function...
Change 14.7.1 [temp.inst] paragraph 1 as follows:
...The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions or default arguments, of the class member functions, member classes, scoped member enumerations, static data members and member templates; and it causes the implicit instantiation of the definitions of unscoped member enumerations and member anonymous unions. Unless a member...
Change 14.7.3 [temp.expl.spec] paragraph 1 as follows:
An explicit specialization of any of the following:
function template
class template
member function of a class template
static data member of a class template
member class of a class template
member enumeration of a class template
member class template of a class or class template
member function template of a class or class template
can be declared by a declaration introduced by template<>...
Change 14.7.3 [temp.expl.spec] paragraph 4 as follows:
A member function, a member class, a member enumeration, or a static data member of a class template may be explicitly specialized for a class specialization that is implicitly instantiated...
Add the indicated text to the example in 14.7.3 [temp.expl.spec] paragraph 6:
template<> void sort<>(Array<char*>& v); //OK: sort<char*>not yet used template<class T> struct A { enum E: T; enum class S: T; }; template<> enum A<int>::E: int { eint }; //OK template<> enum class A<int>::S: int { sint }; //OK template<class T> enum A<T>::E: T { eT }; template<class T> enum class A<T>::S: T { sT }; template<> enum A<char>::E: int { echar }; //ill-formed, A<char>::Ewas instantiated when A<char>was instantiated template<> enum class A<char>::S: int { schar }; //OK
Change 14.7.3 [temp.expl.spec] paragraph 7 as follows:
The placement of explicit specialization declarations for function templates, class templates, member functions of class templates, static data members of class templates, member classes of class templates, member enumerations of class templates, member class templates of class templates, member function templates...
1210. Injection of elaborated-type-specifier in enumeration scope
Proposed resolution:
Change 3.3.2 [basic.scope.pdelc] paragraph 6 bullet 2 as follows:
...otherwise, except as a friend declaration, the identifier is declared in the smallestnon-class, non-function-prototypenamespace or block scope that contains the declaration. [Note:...
1212. Non-function-call xvalues and decltype
Proposed resolution:
Change 7.1.6.2 [dcl.type.simple] paragraph 4 as follows:
The type denoted by decltype(e) is defined as follows:
if e is an unparenthesized id-expression or a class member access (5.2.5 [expr.ref]), decltype(e) is the type of the entity named by e. If there is no such entity, or if e names a set of overloaded functions, the program is ill-formed;
otherwise, if e is
a function call (5.2.2 [expr.call]) or an invocation of an overloaded operator (parentheses around e are ignored), decltype(e) is the return type of the statically chosen functionan xvalue, decltype(e) is T&&, where T is the type of e;otherwise, if e is an lvalue, decltype(e) is T&, where T is the type of e;
otherwise, decltype(e) is the type of e.
1214. Kinds of initializers
Proposed resolution:
Change 8.5 [dcl.init] paragraph 13 as follows:
The form of initialization (using parentheses or =) is generally insignificant, but does matter when the initializer or the entity being initialized has a class type; see below.AIf the entity being initialized does not have class type, the expression-list in a parenthesized initializercanshall be alist of expressions only when the entity being initialized has a class typesingle expression.
Change 8.5 [dcl.init] paragraph 16 as follows:
The semantics of initializers are as follows. The destination type is the type of the object or reference being initialized and the source type is the type of the initializer expression.
TheIf the initializer is not a single (possibly parenthesized) expression, the source type is not definedwhen the initializer is a braced-init-list or when it is a parenthesized list of expressions.
If the initializer is a (non-parenthesized) braced-init-list, the object or reference is list-initialized (8.5.4 [dcl.init.list]).
...
If the destination type is a (possibly cv-qualified) class type:
If the initialization is direct-initialization, or if it is copy-initialization where the cv-unqualified version of the source type is the same class as, or a derived class of, the class of the destination, constructors are considered. The applicable constructors are enumerated (13.3.1.3 [over.match.ctor]), and the best one is chosen through overload resolution (13.3 [over.match]). The constructor so selected is called to initialize the object, with the initializer expression
(s)or expression-list as its argument(s). If no constructor applies, or the overload resolution is ambiguous, the initialization is ill-formed.Otherwise...
1215. Definition of POD struct
Proposed resolution:
Change 9 [class] paragraph 10 as follows:
A POD struct111 is a non-union class that is both a trivial class and a standard-layout class...
1216. Exceptions “allowed” by a noexcept-specification
Proposed resolution
Change 15.4 [except.spec] paragraph 8 as follows:
A function is said to allow an exception of type E if the constant-expression in its noexcept-specification evaluates to false or its dynamic-exception-specification contains a type T for which a handler of type T would be a match (15.3 [except.handle]) for an exception of type E.
1219. Non-static data member initializers in constant expressions
Proposed resolution:
Change 3.6.2 [basic.start.init] paragraph 2 as follows:
if an object with static or thread storage duration is initialized by a constructor call, if the constructor is a constexpr constructor, if all constructor arguments are constant expressions (including conversions), and if, after function invocation substitution (7.1.5 [dcl.constexpr]), every constructor call and full-expression in the mem-initializers and in the brace-or-equal-initializers for non-static data members is a constant expression
Change 3.9 [basic.types] paragraph 10 as follows (wording
assumes the proposed resolution of
A type is a literal type if it is:
a scalar type; or
a class type (clause 9 [class]) that has all of the following properties:
it has a trivial destructor,
every constructor call and full-expression in the brace-or-equal-initializers for non-static data members (if any) is a constant expression (5.19 [expr.const]),
it is an aggregate type (8.5.1 [dcl.init.aggr]) or has at least one constexpr constructor or constructor template that is not a copy or move constructor, and
it has all non-static data members and base classes of literal types; or
an array of literal type.
1220. Looking up conversion-type-ids
Proposed resolution:
Change 3.4.5 [basic.lookup.classref] paragraph 7 of the proposed resolution of issue 1111 as follows:
If the id-expression is a conversion-function-id, its conversion-type-id is first looked up in the class of the object expression and the name, if foundand denotes a type, is used. Otherwise it is looked up in the context of the entire postfix-expressionand the name shall denote a type. In each of these lookups, only names that denote types or templates whose specializations are types are considered.
1224. constexpr defaulted copy constructors
Proposed resolution:
Change 12.8 [class.copy] paragraph 14 as follows:
A copy/move constructor that is defaulted and not defined as deleted is implicitly defined if it is odr-used (3.2 [basic.def.odr]) to initialize an object of its class type from a copy of an object of its class type or of a class type derived from its class type123 or when it is explicitly defaulted after its first declaration. [Note: the copy/move constructor is implicitly defined even if the implementation elided its odr-use (3.2 [basic.def.odr], 12.2 [class.temporary]). —end note] If the implicitly-defined constructor would satisfy the requirements of a constexpr constructor (7.1.5 [dcl.constexpr]), the implicitly-defined constructor is constexpr.
1225. constexpr constructors and virtual bases
Proposed resolution:
Add the following bullet to the list in 7.1.5 [dcl.constexpr] paragraph 4:
the class shall not have any virtual base class;
1229. Overload resolution with empty braced-init-list argument
Proposed resolution:
Change 8.5.4 [dcl.init.list] paragraph 3 bullet 5 as follows:
Otherwise, if T is a class type,
constructors are considered. If T has an
initializer-list constructor, the argument list consists of
the initializer list as a single argument; otherwise, the
argument list consists of the elements of the initializer
list. The applicable constructors are enumerated
(13.3.1.7 [over.match.list]) and the best one
is chosen through overload resolution (13.3.1.7 [over.match.list], 13.3 [over.match]). If a
narrowing conversion (see below) is required to convert any
of the arguments, the program is ill-formed.
[Example:...
Change 13.3.1.7 [over.match.list] as follows:
When objects of non-aggregate class type T are list-initialized (8.5.4 [dcl.init.list]), overload resolution selects the constructor in two phases
as follows, where T is the cv-unqualified class type of the object being initialized:
If T has an initializer-list constructor (8.5.4 [dcl.init.list]),Initially, the candidate functions are the initializer-list constructors (8.5.4 [dcl.init.list]) of the class T and the argument list consists of the initializer list as a single argument.
; otherwise,If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all the constructors of the class T and the argument list consists of the elements of the initializer list.
For direct-list-initialization, the candidate functions are all the constructors of the class T.If the initializer list has no elements and T has a default constructor, the first phase is omitted.
ForIn copy-list-initialization,the candidate functions are all the constructors of T. However,if an explicit constructor is chosen, the initialization is ill-formed. [Note: This differs from other situations (13.3.1.3 [over.match.ctor], 13.3.1.4 [over.match.copy]), where only converting constructors are considered for copy-initialization. This restriction only applies if this initialization is part of the final result of overload resolution. —end note]
(This resolution also resolves issue 1151.)
1231. Variadic templates requiring an empty pack expansion
Proposed resolution:
Change 14.6 [temp.res] paragraph 8 as follows:
Knowing which names are type names allows the syntax of every template definition to be checked. No diagnostic shall be issued for a template definition for which a valid specialization can be generated. If no valid specialization can be generated for a template definition, and that template is not instantiated, the template definition is ill-formed, no diagnostic required. If every valid specialization of a variadic template requires an empty template parameter pack, the template definition is ill-formed, no diagnostic required. If a type used in a non-dependent name... [Example:int j; template<class T> class X {...
}; template<typename ... T> struct A { void operator++(int, T... t); // error: too many parameters }; template<typename ... T> union X: T... { }; // error: union with base class template<typename ... T> struct A: T..., T... { }; // error: duplicate base class—end example]
1232. Creation of array temporaries using a braced-init-list
Proposed resolution:
Change 8.5.4 [dcl.init.list] paragraph 3 bullet 5 as follows:
Otherwise, if T is a reference to class
type or if T is any reference type and the initializer
list has no elements, a prvalue temporary of the type referenced
by T is list-initialized, and the reference is bound to that
temporary. [Note: As usual, the binding will fail and the
program is ill-formed if the reference type is an lvalue reference to
a non-const type. —end note]
[Example:
struct S { S(std::initializer_list<double>); // #1 S(const std::string&); // #2 // ... }; const S& r1 = { 1, 2, 3.0 }; // OK: invoke #1 const S& r2 { "Spinach" }; // OK: invoke #2 S& r3 = { 1, 2, 3 }; // error: initializer is not an lvalue const int& i1 = { 1 }; // OK const int& i2 = { 1.1 }; // error: narrowing const int (&iar)[2] = { 1, 2 }; // OK, iar bound to temporary array
—end example]
Change 13.3.3.1.5 [over.ics.list] paragraph 2 as follows:
If the parameter type is std::initializer_list<X> or “array of X” [Footnote: since there are no parameters of array type, this will only occur as the underlying type of a reference parameter. —end footnote] and all the elements of the initializer list can be implicitly converted to X, the implicit conversion sequence is the worst conversion necessary to convert an element of the list to X. This conversion can be a user-defined conversion even in the context of a call to an initializer-list constructor. [Example:
void f(std::initializer_list<int>); f( {1,2,3} ); // OK: f(initializer_list<int>) identity conversion f( {'a','b'} ); // OK: f(initializer_list<int>) integral promotion f( {1.0} ); // error: narrowing struct A { A(std::initializer_list<double>); // #1 A(std::initializer_list<complex<double>>); // #2 A(std::initializer_list<std::string>); // #3 }; A a{ 1.0,2.0 }; // OK, uses #1 void g(A); g({ "foo", "bar" }); // OK, uses #3 typedef int IA[3]; void h(const IA&); h({1,2,3}); // OK: identity conversion—end example]
1233. Pack expansions and dependent calls
Proposed resolution:
Change 14.6.2 [temp.dep] paragraph 1 as follows:
Inside a template... the id-expression denotes a dependent name if
any of the expressions in the expression-list is a pack expansion (14.5.3 [temp.variadic]),
any of the expressions in the expression-list is a type-dependent expression (14.6.2.2 [temp.dep.expr]), or
the unqualified-id of the id-expression is a template-id in which any of the template arguments depends on a template parameter.
If an operand of an operator...
[Drafting note: this resolution changes some running text in the current wording into a bulleted list, adding one item.
1234. abstract-declarator does not permit ... after ptr-operator
Proposed resolution:
Change the grammar in 8.1 [dcl.name] paragraph 1 as follows:
(This resolution also resolves NB FCD comment CH 8.)
1236. Inconsistently-interrelated examples
Proposed resolution:
Change the examples in 8.5.3 [dcl.init.ref] as follows:
struct A { }; struct B : A { } b; extern B f(); const A& rca2 = f(); // bound to the A subobject of the B rvalue. A&& rra = f(); // same as above struct X { operator B(); operator int&(); } x; const A& r = x; // bound to the A subobject of the result of the conversion int i2 = 42; int&& rri = static_cast<int&&>(i2); // bound directly to i2 B&& rrb = x; // bound directly to the result of operator B int&& rri2 = X(); // error: lvalue-to-rvalue conversion applied to the // result of operator int&
and
const double& rcd2 = 2; // rcd2 refers to temporary with value 2.0 double&& rrd = 2; // rrd refers to temporary with value 2.0 const volatile int cvi = 1; const int& r2 = cvi; // error: type qualifiers dropped double d2 = 1.0; double&& rrd2 = d2; // error: copying lvalue of related type int i3 = 2; double&& rrd3 = i3; // rrd3 refers to temporary with value2.02.0
1237. Deprecated implicit copy assignment in example
Proposed resolution:
Change the example in 12.2 [class.temporary] paragraph 2 as follows:
class X { public: X(int); X(const X&); X& operator=(const X&); ~X(); }; ...
1238. Overloading ambiguity binding reference to function
Proposed resolution:
Add a new bullet 13.3.3.2 [over.ics.rank] paragraph 3, bullet 1, sub-bullet 4
...
S1 and S2 are reference bindings (8.5.3 [dcl.init.ref]) and neither refers to an implicit object parameter...
S1 and S2 are reference bindings (8.5.3 [dcl.init.ref]), and S1 binds an lvalue reference to a function lvalue and S2 binds an rvalue reference to a function lvalue. [Example:
template <class T> int f(T &);
template <class T> int f(T &&);
void g();
int ii = f(g); // Calls f(T &)
S1 and S2 are reference bindings (8.5.3 [dcl.init.ref]), and the types to which the references refer are the same...
Change 13.3.3.1.4 [over.ics.ref] paragraph 3 as follows:
Except for an implicit object parameter, for which see 13.3.1 [over.match.funcs], a standard conversion sequence cannot be formed if it requires binding an lvalue reference other than a reference to a non-volatile const type to an rvalue or binding an rvalue reference to an lvalue other than a function lvalue. [Note:...
1239. Hexadecimal floating-point literals vs user-defined literals
Proposed resolution:
Change 2.14.8 [lext.ext] paragraph 1 as follows:
If a token matches both user-defined-literal and another literal kind, it is treated as the latter. [Example: 123_km, 1.2LL, "Hello"s are all user-defined-literalsis a user-defined-literal, but 12LL is an integer-literal. —end example]
Change 2.14.8 [lex.ext] paragraph 7 as follows:
[Example:
long double operator "" _w(long double); std::string operator "" _w(const char16_t*, size_t); unsigned operator "" _w(const char*); int main() { 1.2_w; // calls operator "" _w(1.2L) u"one"_w; // calls operator "" _w(u"one", 3) 12_w; // calls operator "" _w("12") "two"_w; // error: no applicable literal operator }—end example]
Change 2.14.8 [lex.ext] paragraph 9 as follows:
[Example:
int main() { L"A" "B" "C"_x; // OK: same as L"ABC"_x "P"_x "Q" "R"_y; // error: two different ud-suffixes }—end example]
Insert the following as a new paragraph after 2.14.8 [lex.ext] paragraph 9:
Some identifiers appearing as ud-suffixes are reserved for future standardization (17.6.4.3.5 [usrlit.suffix]). A program containing such a ud-suffix is ill-formed, no diagnostic required.
Change 13.5.8 [over.literal] paragraph 1 as follows:
The identifier in a literal-operator-id is called a literal suffix identifier. [Note: some literal suffix identifiers are reserved for future standardization; see 17.6.4.3.5 [usrlit.suffix]. —end note]
[Note: CWG decided not to require a diagnostic for such ud-suffixes because libraries may wish to use them, which would be more difficult with a mandatory diagnostic.]
1241. Which members does a destructor destroy?
Proposed resolution:
Change 12.4 [class.dtor] paragraph 7 as follows:
After executing the body of the destructor and destroying any automatic objects allocated within the body, a destructor for class X calls the destructors for X's direct non-variant non-static data members, the destructors for X's direct base classes and...
1242. Initializing variant class members
Proposed resolution:
Change 12.6.2 [class.base.init paragraph 5 as follows:
A ctor-initializer may initializethe member of an anonymous union that is aa variant member of the constructor's class...
1243. Misleading footnote regarding multiple-declarator declarations
Proposed resolution:
Change the footnote in 8 [dcl.dcl] paragraph 3 as follows:
A declaration with several declarators is usually equivalent to the corresponding sequence of declarations each with a single declarator. That is
T D1, D2, ... Dn;is usually
equvalentequivalent toT D1; T D2; ... T Dn;where T is a decl-specifier-seq and each Di is an init-declarator.
TheAn exception occurs when a name introduced by one of the declarators hides a type name used by the decl-specifiers, so that when the same decl-specifiers are used in a subsequent declaration, they do not have the same meaning, as instruct S ... ; S S, T; // declare two instances of struct S
which is not equivalent to
struct S ... ; S S; S T; // error
Another exception occurs when T is auto (7.1.6.4 [dcl.spec.auto]), for example:
auto i = 1, j = 2.0; // error: deduced types for i and j don't matchas opposed to
auto i = 1; // OK: i deduced to have type int auto j = 2.0; // OK: j deduced to have type double
1244. Equivalence of alias templates and class templates
Proposed resolution:
Change the example in 14.4 [temp.type] paragraph 1 as follows:
template<template<class> class TTclass T> struct X { }; template<class> struct Y { }; template<class T> using Z = Y<T>; X<Y<int>> y; X<Z<int>> z;
1246. Non-deduced non-final parameter packs
Proposed resolution:
Change 14.1 [temp.param] paragraph 11 as follows:
If a template-parameter of a class template has a default template-argument, each subsequent template-parameter shall either have a default template-argument supplied or be a template parameter pack. If a template-parameter of a primary class template is a template parameter pack, it shall be the last template-parameter.
[Note: These are not requirements for function templates or class template partial specializations because template arguments can be deducedA template parameter pack of a function template shall not be followed by another template parameter unless that template parameter can be deduced or has a default argument (14.8.2 [temp.deduct]). [Example:template<class T1 = int, class T2> class B; // error // U cannot be deduced or specified template<typename... T, typename... U> void f() { } template<typename... T, typename U> void g() { }—end example]
—end note]