如何在不显式调用显式构造函数的情况下初始化映射?
How can I initialize a map without explicitly invoking an explicit constructor?
我正在尝试使用初始化列表初始化 std::map
(在生产中,这是 class 的成员初始化程序,但我的最小失败示例如下)。鉴于
#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
据我所知,无法指定 Alg
类型。无论如何,这就是 explicit
构造函数的意图。只是为了[我不知道在这里说什么],你仍然可以调用 std::pair
的就地构造函数,如下所示。
MyMap m{{std::piecewise_construct, std::forward_as_tuple(1), std::tie(cfg)}};
这样,您就不必键入 Alg
,这样就可以回答您的问题。此外,只有当你讨厌自己和你的同事时才这样做。
注意:std::pair
的就地构造函数实际上存在以允许不可复制、不可移动的类型。
我正在尝试使用初始化列表初始化 std::map
(在生产中,这是 class 的成员初始化程序,但我的最小失败示例如下)。鉴于
#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
据我所知,无法指定 Alg
类型。无论如何,这就是 explicit
构造函数的意图。只是为了[我不知道在这里说什么],你仍然可以调用 std::pair
的就地构造函数,如下所示。
MyMap m{{std::piecewise_construct, std::forward_as_tuple(1), std::tie(cfg)}};
这样,您就不必键入 Alg
,这样就可以回答您的问题。此外,只有当你讨厌自己和你的同事时才这样做。
注意:std::pair
的就地构造函数实际上存在以允许不可复制、不可移动的类型。