Properties of explicit specializations of implicitly-instantiated class templates
13.9.4 [temp.expl.spec]
Mark Hall

Created on 2021-02-02.00:00:00 last changed 1 month ago


Date: 2021-02-02.00:00:00

According to 13.9.4 [temp.expl.spec] paragraph 16,

A member or a member template of a class template may be explicitly specialized for a given implicit instantiation of the class template, even if the member or member template is defined in the class template definition. An explicit specialization of a member or member template is specified using the syntax for explicit specialization.

The relationship between this construct and paragraph 14 is not clear:

Whether an explicit specialization of a function or variable template is inline, constexpr, or an immediate function is determined by the explicit specialization and is independent of those properties of the template.

(See also 9.2.6 [dcl.constexpr] paragraph 1, note 1.) Is this intended to apply to explicit specializations of members of implicitly-instantiated class templates? For example:

  template<typename T> struct S {
    int f();
    constexpr int g();
  template<> constexpr int S<int>::f() {  // OK, constexpr?
    return 0;
  template<> int S<int>::g() {            // OK, not constexpr?
    return 0;

There is implementation divergence on the treatment of this example. This divergence may relate to interpretation of the requirement in 9.2.6 [dcl.constexpr] paragraph 1,

If any declaration of a function or function template has a constexpr or consteval specifier, then all its declarations shall contain the same specifier.

Is an explicit specialization of a member of an implicitly-instantiated class template a declaration of that member? A similar question also applies to the constinit specifier as specified in 9.2.7 [dcl.constinit] paragraph 1:

If the specifier is applied to any declaration of a variable, it shall be applied to the initializing declaration.

(Note that constinit is not mentioned in 13.9.4 [temp.expl.spec] paragraph 14.) For example:

  template<typename T> struct S {
    static constinit T x;
  template<> int S<int>::x = 10;    // constinit required?
  extern char c;
  template<> short S<char>::x = c;  // error, c not constant?

(Possibly relevant is the fact that default arguments are prohibited in explicit specializations of member functions of implicitly-instantiated class templates, per 13.9.4 [temp.expl.spec] bullet 21.3.)

Date User Action Args
2021-02-02 00:00:00admincreate