8

I've declared a class in the following way

class A
{
    struct B
    {
        constexpr
        B(uint8_t _a, uint8_t _b) :
            a(_a),
            b(_b)
        {}

        bool operator==(const B& rhs) const
        {
            if((a == rhs.a)&&
               (b == rhs.b))
            {
                return true;
            }
            return false;
        }

        uint8_t a;
        uint8_t b;
    };

    constexpr static B b {B(0x00, 0x00)};

};

But g++ says

error: field initializer is not constant

Can't figure out where I'm wrong.

2
  • @Manu343726 gcc (Debian 4.7.2-5) 4.7.2 Commented Jul 2, 2014 at 9:35
  • 1
    Read this. I think its exactly the same problem. Commented Jul 2, 2014 at 9:52

2 Answers 2

11

Clang is more helpful:

27 : error: constexpr variable 'b' must be initialized by a constant expression
constexpr static B b {B(0x00, 0x00)};
                   ^~~~~~~~~~~~~~~~
27 : note: undefined constructor 'B' cannot be used in a constant expression
constexpr static B b {B(0x00, 0x00)};
                      ^
8 : note: declared here
B(uint8_t _a, uint8_t _b) :
^

Within a brace-or-equal-initializer of a member variable, constructors (including constructors of nested classes) are considered undefined; this is because it is legitimate for a constructor to refer to the values of member variables, so the member variables must be defined first even if they are lexically later in the file:

struct A {
  struct B { int i; constexpr B(): i{j} {} };
  constexpr static int j = 99;
};

The workaround is to place B outside A, or perhaps within a base class.

Sign up to request clarification or add additional context in comments.

Comments

2

This will work:

#include <cstdint>
#include <iostream>

class A
{
    struct B
    {
        bool operator==(const B& rhs) const
        {
            if((a == rhs.a)&&
               (b == rhs.b))
            {
                return true;
            }
            return false;
        }

        uint8_t a;
        uint8_t b;
    };

  public:
    constexpr static B b {0x61, 0x62};

};

int main() {
    std::cout << '{' << A::b.a << ',' << A::b.b << '}' << std::endl;
}

Removing the constructor from the struct will allow the braces initializer to work. This won't really help you if you were planning on doing something funky in the constructor.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.