I have a class sorta like:
class Object {
public:
struct Flag {
const uint32_t bit = 0;
const wchar_t* name = L"";
const wchar_t sign = L"";
}
static std::map<const char*, Flag> Flags;
}
I'm currently on VS2015, but want to support clang and gcc (the latest). My problem is, I can't figure out how to actually initialize that map with data.
I tried putting it inline, like:
static std::map<const char*, Flag> Flags = {
{ "FOO1", { 0, L"FOO1", L'A' } },
{ "FOO2", { 1, L"FOO3", L'B' } },
{ "FOO3", { 2, L"FOO3", L'C' } }
}
But that complained that only const integral types can be in-class. Okay! So I just left it as the declaration in the class definition (as shown in the first code snippet), and put this in the associated cpp:
static std::map<const char*, Object::Flag> Object::Flags = {
{ "FOO1", { 0, L"FOO1", L'A' } },
{ "FOO2", { 1, L"FOO3", L'B' } },
{ "FOO3", { 2, L"FOO3", L'C' } }
}
Now this complains that:
error C2440: 'initializing': cannot convert from 'initializer list' to 'std::map,std::allocator>>'
The thing is, I could've sworn I've had this working, so I'm thinking I must have the syntax wrong. If not, clearly I'm missing how to load a static map into a classes namespace.
According to the C++11 standard, Flag
is not an aggregate due to the presence of the brace-or-equal-initializers (aka default member initializers), so attempting to use aggregate initialization to initialize it fails. C++14 removed this restriction, so Flag
is considered an aggregate according to that version of the standard, and your code is valid.
Here's a much simpler version of your example that fails to compile with -std=c++11
, but successfully compiles with -std=c++14
.
#include <stdint.h>
struct Flag {
const uint32_t bit = 0;
const wchar_t* name = L"";
const wchar_t sign = L' ';
};
int main()
{
Flag f{ 0U, L"FOO1", L'A' };
}
VS2015 still has the C++11 behavior, so your options are to either remove the default member initializers (thus making Flag
an aggregate), or provide a constructor for Object::Flag
.