我最近偶然发现了初始化列表的一些问题。考虑一个存储类似地图的数据的程序
struct MyMapLike {
MyMapLike(std::map<std::string, int> data)
:data(std::move(data))
{ }
private:
std::map<std::string, int> data;
};
这看起来直截了当。但是当初始化它时,它变得丑陋。我想让它看起来像
MyMapLike maps = { { "One", 1 }, { "Two", 2 } };
但是编译器并不想接受这个,因为上面的意思是它应该寻找一个可以分别接受{ "One", 1 }
和的双参数构造函数{ "Two", 2 }
。我需要添加额外的大括号,使其看起来像一个接受的单参数构造函数{ { ... }, { ... } }
MyMapLike maps = { { { "One", 1 }, { "Two", 2 } } };
我不想那样写。由于我有一个类似映射的类,并且初始化程序具有映射列表的抽象值,因此我想使用以前的版本,并且独立于任何此类实现细节,例如构造函数的嵌套级别。
一种解决方法是声明一个初始化列表构造函数
struct MyMapLike {
MyMapLike(std::initializer_list<
std::map<std::string, int>::value_type
> vals)
:data(vals.begin(), vals.end())
{ }
MyMapLike(std::map<std::string, int> data)
:data(std::move(data))
{ }
private:
std::map<std::string, int> data;
};
现在我可以使用前者,因为当我有一个初始化列表构造函数时,整个初始化列表被视为一个元素,而不是被拆分为多个元素。但我认为构造函数的这种单独需求非常丑陋。
我正在寻找指导:
- 您如何看待前一种和后一种形式的初始化?在这种情况下需要额外的大括号是否有意义?
- 您认为在这种情况下添加初始化列表构造函数的要求很糟糕吗?
如果你同意我的观点,前一种初始化方式更好,你能想到什么解决方案?