Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static constexpr members of same type as class defined (additional details)

While writing my initial question, if this is even possible, I stumbled about the question static constexpr member of same type as class being defined, which quite clearly answered that my clean solution is not possible with C++11.

But then I came up with this code which is quite close to the original poster and I want to achieve:

class MyEnum
{
public:
    constexpr MyEnum() : m_null(true), m_value(0) { }
    constexpr MyEnum(const unsigned int v) : m_null(false), m_value(v) { }

    constexpr operator unsigned int() const { return m_value; }

    static constexpr const MyEnum one() { return MyEnum(1); }

private:
    bool m_null;
    unsigned int m_value;
};

So I'm rephrasing my question: Why does the solution for one compile and can be used as you would expect it but the following solutions give errors about using an incomplete class?

class MyEnum
{
public:
    // snip...

    static constexpr const MyEnum two = MyEnum(2);
    static constexpr const MyEnum three = 3;

    // snip...
}
like image 509
Hurzelchen Avatar asked May 20 '15 22:05

Hurzelchen


People also ask

What does static constexpr mean?

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 same as #define?

#define directives create macro substitution, while constexpr variables are special type of variables. They literally have nothing in common beside the fact that before constexpr (or even const ) variables were available, macros were sometimes used when currently constexpr variable can be used.

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.

Is constexpr implicitly static?

constexpr is a compile time feature, where inline/static are runtime features. The meaning of constexpr is more restricted than static. The meaning is that given a particular input value the return value is always the same, and the copiler ought to be able to work it out completely during compilation.


1 Answers

As @dyp mentioned the solution for one compiles because function definitions are compiled after the class body. So it is like one has been declared like this

class MyEnum
{
public:
    static constexpr const MyEnum one();
    //... Definition here
};  //Class is fully defined after here

inline static constexpr const MyEnum MyEnum::one() { return MyEnum(1); }
                      //Fine here because class is complete ^^^^

On the other hand, definitions in the class body are compiled as they are placed in the class body. So when two and three are being compiled the class is not fully defined yet.

like image 68
phantom Avatar answered Sep 23 '22 13:09

phantom