【问题标题】:How can I initialize a map without explicitly invoking an explicit constructor?如何在不显式调用显式构造函数的情况下初始化地图?
【发布时间】: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


【解决方案1】:

据我所知,没有办法指定Alg 类型。这就是explicit 构造函数的意图。只是为了[我不知道在这里说什么],您仍然可以调用std::pair 的就地构造函数,如下所示。

MyMap m{{std::piecewise_construct, std::forward_as_tuple(1), std::tie(cfg)}};

这样,您不必输入Alg,这可以回答您的问题。此外,只有在您讨厌自己和您的同事时才执行上述操作。

注意:std::pair 的就地构造函数实际上存在以允许不可复制、不可移动的类型。

【讨论】:

    猜你喜欢
    • 2018-07-22
    • 2012-08-16
    • 2021-12-16
    • 2013-02-01
    • 2015-10-24
    • 1970-01-01
    • 2013-11-03
    • 2019-12-24
    • 1970-01-01
    相关资源
    最近更新 更多