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.
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.
[Accepted as a DR at the February, 2023 meeting.] According to 13.9.4 [temp.expl.spec] paragraph 16, The relationship between this construct and paragraph
14 is not clear: (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: 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, 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: (Note that constinit is not mentioned in
13.9.4 [temp.expl.spec] paragraph 14.) For example: (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.)
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.
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.
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;
}
If any declaration of a function or function template has a
constexpr or consteval specifier, then
all its declarations shall contain the same specifier.
If the specifier is applied to any declaration of a
variable, it shall be applied to the initializing
declaration.
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?