如何在不显式调用显式构造函数的情况下初始化地图?

时间:2019-05-02 19:11:57

标签: c++ stdmap initializer-list

我正在尝试使用初始化列表初始化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的文档时,我迷失了在什么时候构造函数是显式的。

第三种情况是显式构造。出于可维护性的原因,我宁愿不这样做。

似乎我已经读到很多初始化器列表的反直觉问题可以通过添加更多的花括号来解决(粗略的简化),但我承认我现在迷失了。

如果我删除了explicit构造函数的Alg限定条件,则所有三种情况都将编译。但是,我不确定提供隐式转换只是为了简化初始化程序列表是否有意义。

是否可以在不显式构造Alg成员的情况下初始化地图元素?使用g ++ 7.3

1 个答案:

答案 0 :(得分:1)

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

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

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

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