我有一个类排序为:
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;
}
我目前正在使用VS2015,但希望支持clang和gcc(最新版本)。我的问题是,我不知道如何用数据初始化映射。
我试着把它放在内联中,比如:
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' } }
}
但它抱怨说,类中只能有const积分类型。可以所以我只是把它作为类定义中的声明(如第一个代码片段所示),并把它放在相关的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' } }
}
现在这抱怨道:
error C2440: 'initializing': cannot convert from 'initializer list' to 'std::map,std::allocator>>'
问题是,我本可以发誓我已经完成了这项工作,所以我想我一定是语法错误了。如果没有,很明显我错过了如何将静态映射加载到类命名空间中。
不能使用列表初始化语法{ 0, L"FOO1", L'A' }
初始化Object::Flag
的对象,因为它有默认的成员初始化器。看见http://en.cppreference.com/w/cpp/language/list_initialization了解更多详细信息。
不能使用表单的聚合初始化
Object::Flag f = { 0, L"FOO1", L'A'};
出于同样的原因。看见http://en.cppreference.com/w/cpp/language/aggregate_initialization.
将Object::Flag
更改为更简单的形式:
struct Flag {
const uint32_t bit;
const wchar_t* name;
const wchar_t sign;
};
然后你应该能够使用:
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' } }};
之后,您还应该能够使用:
Object::Flag f = { 0, L"FOO1", L'A'};
根据C++11标准,由于存在大括号或相等的初始化器(也称为默认成员初始化器),Flag
不是聚合,因此尝试使用聚合初始化对其进行初始化失败。C++14删除了此限制,因此根据该版本的标准,Flag
被视为聚合,并且您的代码是有效的。
以下是您的示例的一个简单得多的版本,它无法使用-std=c++11
进行编译,但使用-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仍然具有C++11行为,因此您可以选择删除默认的成员初始值设定项(从而使Flag
成为聚合),或者为Object::Flag
提供构造函数。