Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why is an uninitialized constexpr variable not constant?

I'm not sure if this is a compiler bug or if I misunderstand constexpr:

struct S{};
constexpr S s1{};
constexpr S s2;

struct test{
    static constexpr auto t1 = s1;
    static constexpr auto t2 = s2;  //error here
};

GCC 4.8 is giving me an odd error "error: field initializer is not constant". Is s2 really not a constant? If so why?

For clarity I actually am using a bunch of empty structs in my code (for meta programming https://github.com/porkybrain/Kvasir) so I really am interested in this specific example.

like image 867
odinthenerd Avatar asked Mar 27 '15 18:03

odinthenerd


People also ask

Is constexpr constant?

The keyword constexpr was introduced in C++11 and improved in C++14. It means constant expression. Like const , it can be applied to variables: A compiler error is raised when any code attempts to modify the value.

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.

Does constexpr have to be static?

A non-static data member cannot be constexpr. static constexpr int x = 5; int y; };

Should I use const with constexpr?

const can only be used with non-static member functions whereas constexpr can be used with member and non-member functions, even with constructors but with condition that argument and return type must be of literal types.


1 Answers

Update: The code should compile, because [class.ctor]/5 reads:

The implicitly-defined default constructor performs the set of initializations of the class that would be performed by a user-written default constructor for that class with no ctor-initializer (12.6.2) and an empty compound-statement. If that user-written default constructor would satisfy the requirements of a constexpr constructor (7.1.5), the implicitly-defined default constructor is constexpr.

And since S is just an empty struct, the implicitly defined default constructor is empty and thus satisfying constexpr requirements.

So here you are dealing with imperfection of the compilers, which you have to workaround somehow.


Old answer:

Clang emits more sensible error message:

main.cpp:3:13: error: default initialization of an object of const type 'const S' 
requires a user-provided default constructor
constexpr S s2;
            ^

[dcl.constexpr]/9 provides the explanation and even almost exactly your code as an example:

A constexpr specifier used in an object declaration declares the object as const. Such an object shall have literal type and shall be initialized.(...) [ Example:

struct pixel {
    int x, y;
};
constexpr pixel ur = { 1294, 1024 };// OK
constexpr pixel origin; // error: initializer missing

—end example ]

like image 62
Anton Savin Avatar answered Sep 24 '22 12:09

Anton Savin