Reputation: 127
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.
Upvotes: 8
Views: 1331
Reputation: 157484
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.
Upvotes: 11
Reputation: 14426
#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.
Upvotes: 2