【发布时间】:2019-05-02 19:11:57
【问题描述】:
我正在尝试使用初始化器列表初始化std::map(在生产中,这是一个类的成员初始化器,但我的最小失败示例如下)。给定
#include <map>
struct Cfg {};
struct Alg
{
explicit Alg(Cfg const&) {}
};
using MyMap = std::map<int, Alg>;
int main()
{
Cfg cfg;
MyMap m = {
{1, {cfg}}, // error #1
{2, cfg}, // error #2
{3, Alg(cfg)}, // works fine
};
return 0;
}
编译时,错误 #1 是:
foo.cc: In function ‘int main()’:
foo.cc:22:5: error: converting to ‘const Alg’ from initializer list would use
explicit constructor ‘Alg::Alg(const Cfg&)’
};
^
这很简单。将 Cfg 传递给初始化程序需要转换,并且显式构造函数禁止它。
错误 #2 是
foo.cc: In function ‘int main()’:
foo.cc:22:5: error: converting to ‘std::pair<const int, Alg>’ from initializer list would use explicit constructor ‘constexpr std::pair<_T1, _T2>::pair(_U1&&, _U2&&) [with _U1 = int; _U2 = Cfg&; typename std::enable_if<(std::_PCC<true, _T1, _T2>::_MoveConstructiblePair<_U1, _U2>() && (! std::_PCC<true, _T1, _T2>::_ImplicitlyMoveConvertiblePair<_U1, _U2>())), bool>::type <anonymous> = 0; _T1 = const int; _T2 = Alg]’
};
^
这有点令人困惑。我认为该错误涉及隐式调用显式 std::pair 构造函数;阅读std::pair 的文档时,我迷失了哪些构造函数是显式的。
第三种情况是显式构造。出于可维护性的原因,我宁愿不这样做。
似乎我已经读过许多初始化列表违反直觉的问题可以通过添加更多大括号(粗略简化)来解决,但我承认我在这一点上迷路了。
如果我删除Alg 构造函数的explicit 限定,所有三种情况都会编译。但是,我不确定仅仅为了简化初始化列表而提供隐式转换是否有意义。
有没有办法在不显式构造Alg 成员的情况下初始化我的地图元素?使用 g++ 7.3
【问题讨论】:
-
您提供了
explicit。您注意到删除它可以解决问题。似乎您希望启用隐式构造,但前提是它对您来说很方便。你必须选择其中之一。如果您希望编译器仅在您要求时允许隐式构造,则相当于根本没有任何隐式构造。在这两种情况下,您都必须告诉编译器允许构造。 -
也许我还不够清楚什么是隐式构造。
Alg a1(cfg);和Alg a2{cfg};是显式的,但Alg a3 = cfg;和Alg a4 = {cfg};是隐式的 -
@jwm 隐式构造是指从
cfg隐式构造Alg类型的对象。如果您有f(Alg)并调用f(cfg),则必须隐式构造Alg,如果构造函数是显式的,则不允许这样做。
标签: c++ stdmap initializer-list