我最近在初始化列表中遇到了一些问题。考虑一个存储地图状数据的程序从初始化程序列表初始化,但没有{{{{{{{{...}}}}}}}}?
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 } } };
我不希望把它写这样的。因为我有一个类似map的类,并且初始化程序具有映射列表的抽象值,所以我想使用前一个版本,并且独立于任何这样的实现细节,比如构造函数的嵌套层次。
一个解决办法是宣布一个初始化列表构造
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;
};
现在我可以用前者,因为当我有一个初始化列表构造,整个初始化列表作为一个元素,而不是治疗被分解成元素。但我认为构造函数的这个单独的需求是丑陋的。
我在寻找指导:
- 你认为怎么样初始化前者和后者的形式?在这种情况下需要额外的支架是否有意义?
- 您是否认为在这种情况下添加初始化程序列表构造函数的要求很差?
如果你同意我的看法,以前的初始化方式更好,你会想到什么解决方案?
@MooingDuck,我想他就是这么做的!请参阅':: value_type'。 – 2013-12-21 20:11:20
“额外”的外部'{}'做与内部不同的东西:它们是大括号初始化语法的一部分,表明构造函数调用正在发生,但是* not *是实际对象的一部分被传递给构造函数。同时,内括号表示映射的初始化程序列表的实际开始。我认为这很有道理,事实上,Clang警告最外面的一系列大括号中的某些(合法的)部分,所以我期望'{{/ * ... stuff ... * /}}'将会变得相当标准他们更喜欢使用大括号初始化语法。 – 2015-12-15 21:34:49