Doc. No.: WG21/N1801, J16/05-0061
Date: 2005-05-02
Reply to: Clark Nelson
Phone: +1-503-712-8433
Email: clark.nelson@intel.com

Proposed resolution of core issue 301

Primary changes for operator function templates

The principle behind these proposed edits is to change the definition of template-id to include operator-function-id cases. class-template-id is introduced as an equivalent to the previous template-id, where the name of the template is restricted to an identifier.

  1. Change the definition of operator-function-id (13.5p1):

    operator-function-id:
    operator operator
    operator operator < template-argument-listopt >

    This undoes the grammar change that was made for core issue 38.

  2. Change the definition of template-id and add a definition of class-template-id (14.2p1):

    template-id:
    template-name < template-argument-listopt >
    operator-function-id < template-argument-listopt >
    class-template-id:
    template-name < template-argument-listopt >
  3. Change 13.5p1:

    A function declaration having one of the following operator-function-ids as its name declares an operator function. A function template declaration having one of the following operator-function-ids as its name declares an operator function template. A specialization of an operator function template is also an operator function. An operator function is said to implement the operator named in its operator-function-id.

  4. Change 14.2p3:

    After name lookup (3.4) finds that a name is a template-name, or refers to a set of overloaded functions any member of which is a function template, if this name is followed by a <, the < is always taken as the beginning delimiter of a template-argument-list and never as a name followed by the less-than operator. When parsing a template-id template-argument-list, the first non-nested >131) is taken as the end of the template-argument-list ending delimiter rather than a greater-than operator.

Secondary changes: references to template-id which should be to class-template-id

References from the grammar are presented first.

  1. Change the definition of nested-name-specifier (5.1p7):

    nested-name-specifier:
    type-name ::
    namespace-name ::
    nested-name-specifier identifier ::
    nested-name-specifier templateopt class-template-id ::
  2. Change the definition of pseudo-destructor-name (5.2p1):

    pseudo-destructor-name:
    ::opt nested-name-specifieropt type-name :: ~ type-name
    ::opt nested-name-specifier template class-template-id :: ~ type-name
    ::opt nested-name-specifieropt ~ type-name
  3. Change the definition of simple-type-specifier (7.1.5.2p1):

    simple-type-specifier:
    ::opt nested-name-specifieropt type-name
    ::opt nested-name-specifier template class-template-id
    char
    wchar_t
    bool
    short
    int
    long
    signed
    unsigned
    float
    double
    void
  4. Change the definition of elaborated-type-specifier (7.1.5.3):

    elaborated-type-specifier:
    class-key ::opt nested-name-specifieropt identifier
    class-key ::opt nested-name-specifieropt templateopt class-template-id
    enum ::opt nested-name-specifieropt identifier
  5. Change the definition of class-name (9p1):

    class-name:
    identifier
    class-template-id
  6. Change the definition of class-head (9p1):

    class-head:
    class-key identifieropt base-clauseopt
    class-key nested-name-specifier identifier base-clauseopt
    class-key nested-name-specifieropt class-template-id base-clauseopt
  7. Change the definition of typename-specifier (14.6p3):

    typename-specifier:
    typename ::opt nested-name-specifier identifier
    typename ::opt nested-name-specifier templateopt class-template-id
  8. Change 3.3.1p3:

    The point of declaration for a class first declared by a class-specifier is immediately after the identifier or class-template-id (if any) in its class-head (Clause 9). The point of declaration for an enumeration is immediately after the identifier (if any) in its enum-specifier (7.2).

  9. Change 3.4.5p6:

    If the nested-name-specifier contains a class template-id class-template-id (14.2), the names in its template-arguments are evaluated looked up in the context in which the entire postfix-expression nested-name-specifier occurs.

  10. Change the grammar-like portion of 7.1.5.3p1:

    class-key identifier ;
    friend class-key ::opt identifier ;
    friend class-key ::opt class-template-id ;
    friend class-key ::opt nested-name-specifier identifier ;
    friend class-key ::opt nested-name-specifier templateopt class-template-id ;
  11. Change 14.2p6:

    A class-template-id that names a class template specialization is a class-name (clause 9).

  12. Change the first sentence of 14.5.4p1:

    A primary class template declaration is one in which the class template name is an identifier. A template declaration in which the class template name is a class-template-id, is a partial specialization of the class template named in the class-template-id. «...»

  13. Change the last bullet of 14.6.2.1p6:

    a class-template-id in which either the template name is a template parameter or any of the template arguments is a dependent type or an expression that is type-dependent or value-dependent.

  14. Change 14.7p3:

    An explicit specialization may be declared for a function template, a class template, a member of a class template or a member template. An explicit specialization declaration is introduced by template<>. In an explicit specialization declaration for a class template, a member of a class template or a class member template, the name of the class that is explicitly specialized shall be a class-template-id. In the explicit specialization declaration for a function template or a member function template, the name of the function or member function explicitly specialized may be a template-id.

  15. Change 14.7.3p9:

    A class-template-id that names a class template explicit specialization that has been declared but not defined can be used exactly like the names of other incompletely-defined classes (3.9).

  16. Change the last bullet of 14.8.2.1p4:

    If P is a class, and P has the form class-template-id, then A can be a derived class of the deduced A. Likewise, if P is a pointer to a class of the form class-template-id, A can be a pointer to a derived class pointed to by the deduced A.

Other secondary changes

  1. Change 3.4.3.1p1, third bullet:

    the names in a template-argument of a template-id are looked up in the context in which the entire postfix-expression qualified-id occurs.

    This is just editorial clarification.

  2. Change 3.4.3.2p1:

    If the nested-name-specifier of a qualified-id nominates a namespace, the name specified after the nested-name-specifier is looked up in the scope of the namespace, except that the names in a template-argument of a template-id are looked up in the context in which the entire postfix-expression qualified-id occurs.

    This is just editorial clarification.

  3. Change 14p2:

    A template-declaration can appear only as a namespace scope or class scope declaration. In a function template declaration, the last component of the declarator-id shall be a template-name or operator-function-id (i.e., not a template-id). [ Note: in a class template declaration, if the class name is a class-template-id, the declaration declares a class template partial specialization (14.5.4). —end note ]

  4. Change 14.3p1:

    There are three forms of template-argument, corresponding to the three forms of template-parameter: type, non-type and template. The type and form of each template-argument specified in a template-id or class-template-id shall match the type and form specified for the corresponding parameter declared by the template in its template-parameter-list.

    From a bottom-up perspective, template-id would seem practically to include class-template-id, so this addition might seem to be redundant. However, from a top-down perspective, some contexts require a template-id, and others require a class-template-id, so they are actually disjoint.

  5. Change 14.4p1:

    Two template-ids or class-template-ids refer to the same class or function if «...»

    Note that 14.4p1 is also heavily modified by the proposed resolution of core issue 354.

  6. Delete 14.5p1:

    A template-id, that is, the template-name followed by a template-argument-list shall not be specified in the declaration of a primary template declaration. [ Example:

    template<class T1, class T2, int I> class A<T1, T2, I> { }; // error
    template<class T1, int I> void sort <T1, I>(T1 data[I]); // error

    —end example ] [ Note: however, this syntax is allowed in class template partial specializations (14.5.4). —end note ]

    This provision is vacuous, because by the definition of primary in 14.5.4p1, it is impossible to violate: if there is a template-argument-list (or delimiters for same) in a class template declaration, it is not a primary declaration. Furthermore, 14.5.4p1 also already contains the requirement that the primary declaration must precede any partial specialization, so there would be no point in trying to reword this to refer to the first declaration of a template.

  7. Change the second bullet of 14.6.2.2p3:

    a template-id or class-template-id that is dependent,

  8. Change 14.7.2p2:

    If the explicit instantiation is for a class, a function or a member template specialization, If the explicit instantiation is for a class or member class, the elaborated-type-specifier in the declaration shall include a class-template-id. If the explicit instantiation is for a function or member function, the unqualified-id in the declaration shall be either a template-id or, where all template arguments can be deduced, a template-name. [ Note: the declaration may declare a qualified-id, in which case the unqualified-id of the qualified-id must be a template-id. —end note ] If the explicit instantiation is for a member function, a member class or a static data member of a class template specialization, the name of the class template specialization in the qualified-id for the member name shall be a class-template-id. An explicit instantiation shall appear in an enclosing namespace of its template. If the name declared in the explicit instantiation is an unqualified name, the explicit instantiation shall appear in the namespace where its template is declared. [ Note: regarding qualified names in declarators, see 8.3. —end note ]

    The problem here is that in an explicit instantiation of a class (or member class), there is no unqualified-id, at least not at the top level. So I broke out the class case separately from the function case. Note also an added reference to class-template-id.