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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With