(VS2015) 尝试用初始化列表中的数据填充静态映射

(VS2015) Attempting to fill a static map with data from initializer list

我有一个 class 有点像:

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 整数类型可以是 in-class。好的!所以我只是将它保留为 class 定义中的声明(如第一个代码片段所示),并将其放入关联的 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>>'

问题是,我本可以发誓我已经成功了,所以我想我一定是语法错误。如果没有,显然我不知道如何将静态映射加载到 classes 命名空间。

您不能使用列表初始化语法 { 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 removed this restriction, so Flag is considered an aggregate according to that version of the standard, and your code is valid.

这是您的示例的一个更简单的版本,它无法使用 -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' };
}

Live demo.

VS2015 仍然具有 C++11 行为,因此您的选择是删除默认成员初始值设定项(从而使 Flag 成为聚合),或为 Object::Flag 提供构造函数。