Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mixing constexpr declarations and const definitions

I came across the following situation:

struct Foo
{
    static constexpr char s[] = "Hello world";
};

const char Foo::s[];

This code snippet compiles with Clang 3.7 (with -std=c++11 and -std=c++14), but GCC (4.8, 6.0, same language settings) gives the error I would have expected:

GCC 4.8:

in.cpp:6:19: error: redeclaration ‘Foo::s’ differs in ‘constexpr’
 const char Foo::s[];
                   ^
in.cpp:3:27: error: from previous declaration ‘Foo::s’
     static constexpr char s[] = "Hello world";
                           ^
in.cpp:6:19: error: declaration of ‘constexpr const char Foo::s [12]’ outside of class is not definition [-fpermissive]
 const char Foo::s[];

GCC 6.0:

‘constexpr’ needed for in-class initialization of static data member ‘const char Foo::s [12]’ of non-integral type [-fpermissive]

I found this old question that seems to discuss mixing constexpr and const, but it focusses on whether initializers are constant expressions, rather on whether definition and declaration can differ with regard to constness.

Is it allowed to provide the definition for a constexpr T static data member as a const T?

like image 388
Kerrek SB Avatar asked Oct 10 '15 12:10

Kerrek SB


People also ask

Are constexpr variables Const?

All constexpr variables are const . A variable can be declared with constexpr , when it has a literal type and is initialized. If the initialization is performed by a constructor, the constructor must be declared as constexpr .

Can constexpr throw exception?

Even though try blocks and inline assembly are allowed in constexpr functions, throwing exceptions or executing the assembly is still disallowed in a constant expression.

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. So, what does constexpr mean?

Do constexpr functions have to be inline?

The only types usable within a constexpr context are literal types. A constant expression or constexpr function may also not invoke a non constexpr function. The constexpr keyword implies inline. Performing computations at compiletime can have many advantages over doing them at runtime.


1 Answers

Your code is well-formed. The constexpr-specifier is not itself part of the type but adds const ([dcl.constexpr]/9), which is present in your second declaration. Although different declarations of one function (or function template) have to agree in constexpr-ness as per [dcl.constexpr]/1, no such rule exists for variable declarations.

See bug #58541, which basically uses your example.

like image 58
Columbo Avatar answered Sep 16 '22 23:09

Columbo