Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does GCC think that the definition of a constexpr static data member must be marked constexpr?

Tags:

[C++14: 7.1.5/1]: The constexpr specifier shall be applied only to the definition of a variable or variable template, the declaration of a function or function template, or the declaration of a static data member of a literal type (3.9). If any declaration of a function, function template, or variable template has a constexpr specifier, then all its declarations shall contain the constexpr specifier. [..]

Notice that the second sentence does not mention "a static data member" the way the first sentence does, so there is no requirement in this passage that all declarations (and here I'm considering a defining declaration specifically) of a constexpr static data member have the constexpr specifier.

I can't find a rule elsewhere to mandate this, either.

Why, then, does GCC reject the following program?

#include <chrono>  using namespace std::chrono_literals;  #define DUR 1000ms  struct T {    static constexpr auto dur_1 = DUR; };  decltype(T::dur_1) T::dur_1;  // main.cpp:12:23: error: 'constexpr' needed for in-class initialization of static data member 'const std::chrono::duration<long int, std::ratio<1l, 1000l> T::dur_1' of non-integral type [-fpermissive]  // decltype(T::dur_1) T::dur_1; //                       ^ 
like image 384
Lightness Races in Orbit Avatar asked Jun 14 '15 16:06

Lightness Races in Orbit


People also ask

Why does constexpr need to be static?

A static constexpr variable has to be set at compilation, because its lifetime is the the whole program. Without the static keyword, the compiler isn't bound to set the value at compilation, and could decide to set it later.

What is static constexpr?

static defines the object's lifetime during execution; constexpr specifies that the object should be available during compilation. Compilation and execution are disjoint and discontiguous, both in time and space. So once the program is compiled, constexpr is no longer relevant.

Is constexpr implicitly static?

constexpr functions are implicitly inline , but not implicitly static .

How do I know if a function is constexpr?

The easiest way to check whether a function (e.g., foo ) is constexpr is to assign its return value to a constexpr as below: constexpr auto i = foo(); if the returned value is not constexpr compilation will fail.


1 Answers

This looks underspecified to me, I don't see an explicit requirement but we can see why it is an issue from defect report 699: Must constexpr member functions be defined in the class member-specification? which although dealing with constexpr member functions says the following (emphasis mine):

If the prohibition were relaxed to allow separate declaration and definition of constexpr member functions, some questions would need to be answered, such as whether the constexpr specifier must appear on both declaration and definition (the inline specifier need not). If it can be omitted in one or the other, there's a usability issue regarding the fact that constexpr implies const; the const qualifier would need to be specified explicitly in the declaration in which constexpr was omitted.

Although in this case adding const does not solve the problem although in a simpler cases it does seem to solve the issue. We can see in a simpler case both clang and gcc require either const or constexpr:

struct T {    static constexpr int blah = 1 ; };  const int T::blah ; 

Update

This gcc bug report: Bogus "error: redeclaration ... differs in ‘constexpr’" has the following quote from Richard Smith:

There is no rule requiring successive declarations of variables to agree in 'constexpr'ness (this rule only applies to functions).

So this looks like a gcc bug, although it still seems like it could use some clarity in the standard.

like image 172
Shafik Yaghmour Avatar answered Sep 28 '22 07:09

Shafik Yaghmour