Document:  PL22.16/11-0032 = WG21 N3262
Author:    William M. (Mike) Miller
Edison Design Group, Inc.
Date:   2011-03-25





Additional Core Language Issue Resolutions for Madrid

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 of at which the member is defined. The definition of an explicitly specialized class... Definitions of members Members of an explicitly specialized class template are defined in the same manner as members of normal classes, and not using the template<> syntax for 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 syntax template<> not used for a member of an
  // explicitly specialized class template specialization
  void 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 the a 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: [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...
[Drafting note: this resolution transforms the running text of the first sentence of 8.3.5 paragraph 6 into a bulleted list.]


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 scope entity, 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 g is a friend and 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:

  1. Change 5.2.1 [expr.sub] paragraph 2 as follows:

  2. 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 list shall 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]

  3. Change 13.5.5 [over.sub] paragraph 1 as follows:

  4. operator[] shall be a non-static member function with exactly one parameter. It implements the subscripting syntax

    or

    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-list as 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 the specified 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 the injected-class-name template-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-list as 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-list used 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:

...The optional attribute-specifier-seq in a simple-declaration appertains to each of the entities declared by the declarators; it shall not appear if the optional of the init-declarator-list is 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 would otherwise be 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:

  1. Change 9.2 [class.mem] paragraph 7 as follows:

  2. The decl-specifier-seq is may 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...
  3. Change C.1.5 [diff.dcl], “Banning implicit int,” as follows:

  4. 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:

  1. Change the grammar in 7 [dcl.dcl] paragraph 1 as follows:

  2. Change 7.1.3 [dcl.typedef] paragraph 2 as follows:

  3. 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:

  1. Change 3.9.1 [basic.fundamental] paragraph 9 as follows:

  2. ...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, or as 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.
  3. Change 5.16 [expr.cond] paragraph 2 as follows:

  4. If either the second or the third operand has type (possibly cv-qualified) void, then...
  5. Change 6.6.3 [stmt.return] paragraph 3 as follows:

  6. A return statement with an expression of type cv void 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




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-nameend 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:




1082. Implicit copy function if subobject has none?

Proposed resolution:

  1. Change 12.8 [class.copy] paragraph 8 as follows:

  2. 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 declaration The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor. Thus, for the class definition...
  3. Change 12.8 [class.copy] paragraph 19 as follows:

  4. 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 declaration The 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...
  5. Change D.3 [depr.impldec] paragraph 1 as follows:

  6. The implicit declaration definition of a copy constructor as defaulted is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor. The implicit declaration definition 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:

  1. Add a new paragraph at the end of 14.6.2.3 [temp.dep.constexpr]:

  2. An id-expression is value-dependent if it names a member of an unknown specialization.
  3. Change 14.6.2.4 [temp.dep.temp] paragraphs 2-3 as follows:

  4. An integral A non-type template-argument is dependent if its type is dependent or the constant expression it specifies is value-dependent.

    A non-integral Furthermore, a non-type template-argument is dependent if its type is dependent or it has either of the following forms

    and contains a nested-name-specifier which specifies a class-name that names a dependent type the 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:

  1. Change 8.5 [dcl.init] paragraph 16 bullet 1 as follows:

  2. Change 8.5.4 [dcl.init.list] paragraph 3 bullet 7 as follows:




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 of const literal integral 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:

  1. Change 15.3 [except.handle] paragraph 1 as follows:

  2. 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*.
  3. Change 15.3 [except.handle] paragraph 16 as follows:

  4. The object declared in an exception-declaration or, if the exception-declaration If 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. The object is destroyed lifetime 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 variable or non-overloaded function whose 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 functions is odr-used if it is selected 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 declaration program 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 type with a non-static data member to which an extended alignment has been applied to 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:

[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 ignored for in determining the language linkage of the names of class members and the member function 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:

(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. Two distinct objects that are neither not bit-fields nor base class subobjects of zero size shall have distinct addresses may 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, if a pointer value that is not a safely-derived pointer value is dereferenced or deallocated, and an invalid pointer value, unless the referenced complete object is of dynamic storage duration and has not previously been declared reachable (20.9.10 [util.smartptr]), the behavior is undefined. [Note: this The 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 the last four preceding requirements from the list above shall 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 parameters arguments, 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 the one 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 to the 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 call the 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:

  1. Change the grammar 6.5 [stmt.iter] paragraph 1 as follows:

  2. Add the following as a new paragraph at the end of 6.5.4 [stmt.ranged]:

  3. 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:

  1. Change 14 [temp] paragraph 1 as follows:

  2. ...The declaration in a template-declaration shall

  3. Change 14.5.1 [temp.class] paragraph 3 as follows:

  4. 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...
  5. Add a new section following 14.5.1.3 [temp.static]:

  6. 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]

  7. Change 14.7 [temp.spec] paragraph 2 as follows:

  8. 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...
  9. Change 14.7.1 [temp.inst] paragraph 1 as follows:

  10. ...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...
  11. Change 14.7.3 [temp.expl.spec] paragraph 1 as follows:

  12. An explicit specialization of any of the following:

  13. Change 14.7.3 [temp.expl.spec] paragraph 4 as follows:

  14. 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...
  15. Add the indicated text to the example in 14.7.3 [temp.expl.spec] paragraph 6:

  16.   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>::E was instantiated when A<char> was instantiated
      template<> enum class A<char>::S: int { schar }; // OK
    
  17. Change 14.7.3 [temp.expl.spec] paragraph 7 as follows:

  18. 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 smallest non-class, non-function-prototype namespace 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:




1214. Kinds of initializers

Proposed resolution:

  1. Change 8.5 [dcl.init] paragraph 13 as follows:

  2. 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. A If the entity being initialized does not have class type, the expression-list in a parenthesized initializer can shall be a list of expressions only when the entity being initialized has a class type single expression.
  3. Change 8.5 [dcl.init] paragraph 16 as follows:

  4. 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. The If the initializer is not a single (possibly parenthesized) expression, the source type is not defined when the initializer is a braced-init-list or when it is a parenthesized list of expressions.




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:

  1. Change 3.6.2 [basic.start.init] paragraph 2 as follows:

  2. Change 3.9 [basic.types] paragraph 10 as follows (wording assumes the proposed resolution of )

  3. A type is a literal type if it is:



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 found and denotes a type, is used. Otherwise it is looked up in the context of the entire postfix-expression and 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:




1229. Overload resolution with empty braced-init-list argument

Proposed resolution:

  1. Change 8.5.4 [dcl.init.list] paragraph 3 bullet 5 as follows:

  2. Change 13.3.1.7 [over.match.list] as follows:

  3. 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 the initializer list has no elements and T has a default constructor, the first phase is omitted. For In 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:

  1. Change 8.5.4 [dcl.init.list] paragraph 3 bullet 5 as follows:

  2. Change 13.3.3.1.5 [over.ics.list] paragraph 2 as follows:

  3. 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

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 value 2.0 2.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:

  1. Add a new bullet 13.3.3.2 [over.ics.rank] paragraph 3, bullet 1, sub-bullet 4

  2. Change 13.3.3.1.4 [over.ics.ref] paragraph 3 as follows:

  3. 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:

  1. Change 2.14.8 [lext.ext] paragraph 1 as follows:

  2. 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 is a user-defined-literal, but 12LL is an integer-literal. —end example]
  3. Change 2.14.8 [lex.ext] paragraph 7 as follows:

  4. [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]

  5. Change 2.14.8 [lex.ext] paragraph 9 as follows:

  6. [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]

  7. Insert the following as a new paragraph after 2.14.8 [lex.ext] paragraph 9:

  8. 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.
  9. Change 13.5.8 [over.literal] paragraph 1 as follows:

  10. 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 initialize the member of an anonymous union that is a a 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 equvalent equivalent to

  T D1; T D2; ... T Dn;

where T is a decl-specifier-seq and each Di is an init-declarator. The An 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 in

  struct 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 match

as 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 TT class 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 deduced A 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]