(VS2015)正在尝试用初始值设定项列表中的数据填充静态映射

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

本文关键字:列表 数据 映射 静态 填充 VS2015      更新时间:2023-10-16

我有一个类排序为:

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提供构造函数。