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


2409. Explicit specializations of constexpr static data members

Section: 13.9.4  [temp.expl.spec]     Status: drafting     Submitter: Mike Miller     Date: 2019-04-29

The status of an example like the following is not clear:

  struct S {
    template <int N> static constexpr inline int m = N;
  };
  template <> constexpr inline int S::m<5>;

Some implementations accept this, apparently on the basis of allowing and ignoring a redeclaration of a constexpr static data member outside its class, although there is implementation divergence. Most or all implementations, however, diagnose an attempt to use such a specialization in a constant context.

Should it be required to have a definition of the explicit specialization in order to declare it outside the class in such cases?

In addition, most or all implementations accept a version of the example in which the explicit specialization contains an initializer, including allowing its use in constant contexts:

  template <> constexpr inline int S::m<5> = 2;

This would seem to be disallowed both by 11.4.9.3 [class.static.data] paragraph 3,

An inline static data member may be defined in the class definition and may specify a brace-or-equal-initializer. If the member is declared with the constexpr specifier, it may be redeclared in namespace scope with no initializer (this usage is deprecated; see _N4778_.D.4 [depr.static_constexpr]).

which prohibits an initializer, and 13.9.4 [temp.expl.spec] paragraph 2,

An explicit specialization may be declared in any scope in which the corresponding primary template may be defined (_N4868_.9.8.2.3 [namespace.memdef], 11.4 [class.mem], 13.7.3 [temp.mem]).

since the definition of a constexpr static data member is inside the class.

Notes from the May, 2019 teleconference:

These examples should behave in the same way as if the class were templated: instantiate the declaration and the definition of the static data member separately. The first example should be ill-formed, because the explicit specializaation does not have an initializer.