Closed ranaanoop closed 6 months ago
Compilers do have some problem when using class template with const static
data members that are later defined as constexpr
. Another related question/thread: Why class templates don't allow const static data member to be defined outside the class as constexpr.
I'm not seeing any issue here except for those addressed in CWG2800.
It's clear in [dcl.constinit] p1 that constinit
can be applied to a non-initializing declaration, so the type of the variable doesn't need to be complete at that point. On the other hand, [dcl.constexpr] p6 indicates that constexpr
requires the declaration of variable to be initializing.
It's clear in [dcl.constinit] p1 that constinit can be applied to a non-initializing declaration
@frederick-vs-ja dcl.constinit.sentence-2 seems to suggest the opposite to what you're saying. It says:
The constinit specifier shall be applied only to a declaration of a variable with static or thread storage duration. If the specifier is applied to any declaration of a variable, it shall be applied to the initializing declaration. No diagnostic is required if no constinit declaration is reachable at the point of the initializing declaration.
Note the emphasis on "initializing declaration" which means static const constinit Vector ZeroVector;
in snippet 1 is invalid. Did you misread this perhaps?
@frederick-vs-ja dcl.constinit.sentence-2 seems to suggest the opposite to what you're saying. It says:
The constinit specifier shall be applied only to a declaration of a variable with static or thread storage duration. If the specifier is applied to any declaration of a variable, it shall be applied to the initializing declaration. No diagnostic is required if no constinit declaration is reachable at the point of the initializing declaration.
Note the emphasis on "initializing declaration" which means
static const constinit Vector ZeroVector;
in snippet 1 is invalid. Did you misread this perhaps?
This paragraph means that constinit
can be applied to both initializing and non-initializing declarations of a variable. Once applied, it is mandatory for an initializing declaration, while being optional for a non-initializing one.
In other words, "it shall be applied to the initializing declaration" doesn't mean that "the declaration to which it is applied shall be initializing".
It was also said in P1143R2 that
After EWG discussion,
constinit
is permitted on any declarations of a variable; if it is present on some declaration but not on the initializing declaration, the program is ill-formed, no diagnostic required.
@frederick-vs-ja I see. So both of the snippets in the original issue are well-formed.
Full name of submitter: Anoop Rana
Link to reflector thread (if any): https://stackoverflow.com/questions/78248691/static-data-member-of-template-class-type-constexpr-vs-const-constinit
Issue description:
Currently we can define a const static data member outside the class as
constexpr
as also noted in CWG 2800.The problem is that all compilers seems to compile the following invalid(afaik) program, even though the declaration of
ZeroVector
inside the class template usesconst constinit
instead of justconst
. DemoThe correct way to do this would be to remove the
const constinit
from the declaration that is inside the class and replace it withconst
. That is, theconst constinit
should only be in the definition outside the class as shown below:So, is snippet 1 supposed to be ill-formed or well-formed? Afaik snippet 1 is intended to be ill-formed and only snippet 2 is well-formed.