Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

static constexpr member variable initialization

I have the following code:

struct Foo
{       
    struct Bar
    {
        std::uint32_t x = -1;

        constexpr Bar(std::uint32_t x) : x(x) {}
    };

    static constexpr Bar CONST_BAR = Bar(0);
};

When I try to compile it I get the following error:

error: ‘constexpr Foo::Bar::Bar(uint32_t)’ called in a constant expression before its definition is complete

Can someone explain to me what is going on? As far as I can see Bar's constructor is defined before the first call.

Live example

like image 306
rozina Avatar asked Jun 02 '20 08:06

rozina


People also ask

Are constexpr variables static?

It may contain local variable declarations, but the variable must be initialized. It must be a literal type, and can't be static or thread-local. The locally declared variable isn't required to be const , and may mutate. A constexpr non- static member function isn't required to be implicitly const .

Can a member function be 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.

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 does constexpr mean in C++?

The constexpr specifier declares that it is possible to evaluate the value of the function or variable at compile time. Such variables and functions can then be used where only compile time constant expressions are allowed (provided that appropriate function arguments are given).


1 Answers

I don't have a detailed explanation but I happened to have stumbled upon this problem as well and thought it was at least worth mentioning... Other than placing the definition of CONST_BAR outside of struct Foo, another possible workaround is instantiating Foo:

// Example program
#include <iostream>
#include <string>

template<typename T = void>
struct Foo
{       
    struct Bar
    {
        std::uint32_t x = -1;
    
        constexpr Bar(std::uint32_t x) : x(x) {}
    };
    
    static constexpr Bar CONST_BAR = Bar(0);
};

int main()
{
    std::cout << "x: " << Foo<>::CONST_BAR.x << "\n";
}
like image 143
303 Avatar answered Sep 23 '22 23:09

303