Title
Properties of explicit specializations of implicitly-instantiated class templates
Status
c++23
Section
13.9.4 [temp.expl.spec]
Submitter
Mark Hall

Created on 2021-02-02.00:00:00 last changed 9 months ago

Messages

Date: 2023-02-10.23:01:52

Proposed resolution (approved 2023-02-09):

Change in 13.9.4 [temp.expl.spec] paragraph 13 as follows:

Whether an explicit specialization of a function or variable template is inline, constexpr, constinit, or consteval an immediate function is determined by the explicit specialization and is independent of those properties of the template.
Date: 2022-11-11.15:15:16

CWG 2022-11-10

A specialization of a member of a class template redeclares the member of the primary template and thus the redeclaration rules apply. In passing, it was noticed that the rule governing explicit specializations in general omitted treatment of constinit, which was considered an oversight.

Date: 2023-02-15.00:00:00

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

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

History
Date User Action Args
2023-07-16 13:00:43adminsetstatus: open -> c++23
2023-07-16 13:00:43adminsetstatus: dr -> open
2023-02-18 18:43:04adminsetstatus: ready -> dr
2023-02-10 23:01:52adminsetstatus: review -> ready
2022-11-11 15:15:16adminsetmessages: + msg7019
2022-11-11 15:15:16adminsetmessages: + msg7001
2022-11-11 15:15:16adminsetstatus: open -> review
2021-02-02 00:00:00admincreate