This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-11-11


581. Can a templated constructor be explicitly instantiated or specialized?

Section: 13.10.2  [temp.arg.explicit]     Status: CD5     Submitter: Mark Mitchell     Date: 19 May 2006

[Accepted as a DR at the February, 2019 meeting.]

Although it is not possible to specify a constructor's template arguments in a constructor invocation (because the constructor has no name but is invoked by use of the constructor's class's name), it is possible to “name” the constructor in declarative contexts: per 6.5.5.2 [class.qual] paragraph 2,

In a lookup in which the constructor is an acceptable lookup result, if the nested-name-specifier nominates a class C, and the name specified after the nested-name-specifier, when looked up in C, is the injected-class-name of C ( Clause 11 [class]), the name is instead considered to name the constructor of class C... Such a constructor name shall be used only in the declarator-id of a declaration that names a constructor.

Should it therefore be possible to specify template-arguments for a templated constructor in an explicit instantiation or specialization? For example,

    template <int dim> struct T {};
    struct X {
      template <int dim> X (T<dim> &) {};
    };

    template X::X<> (T<2> &);

If so, that should be clarified in the text. In particular, 11.4.5 [class.ctor] paragraph 1 says,

Constructors do not have names. A special declarator syntax using an optional sequence of function-specifiers (9.2.3 [dcl.fct.spec]) followed by the constructor's class name followed by a parameter list is used to declare or define the constructor.

This certainly sounds as if the parameter list must immediately follow the class name, with no allowance for a template argument list.

It would be worthwhile in any event to revise this wording to utilize the “considered to name” approach of 6.5.5.2 [class.qual]; as it stands, this wording sounds as if the following would be acceptable:

    struct S {
        S();
    };
    S() { }    // qualified-id not required?

Notes from the October, 2006 meeting:

It was observed that explicitly specifying the template arguments in a constructor declaration is never actually necessary because the arguments are, by definition, all deducible and can thus be omitted.

Additional notes, October, 2018:

The wording in 13.10.2 [temp.arg.explicit] paragraph 1 refers to a “function name,” which constructors do not have, and so presumably the current wording does not permit an explicit specialization of a constructor template. Nevertheless, there is implementation divergence in the treatment of an example like:

  class C {
    template <typename T>
    C(const T &) {}
  };
  template C::C<double>(const double &);

with some accepting and some rejecting.

Notes from the October, 2018 teleconference:

The consensus was to allow template arguments on the constructor name but not something like C<int>::C<float>::f.

Proposed resolution (February, 2019):

  1. Cbange 13.10.2 [temp.arg.explicit] paragraph 1 as follows:

  2. Template arguments can be specified when referring to a function template specialization that is not a specialization of a constructor template by qualifying the function template name with the list of template-arguments in the same way as template-arguments are specified in uses of a class template specialization. [Example:
  3. Add the following as a new paragraph following 13.10.2 [temp.arg.explicit] paragraph 1:

  4. Template arguments shall not be specified when referring to a specialization of a constructor template (11.4.5 [class.ctor], 6.5.5.2 [class.qual]).