【问题标题】:Why can I pass a boost map_list_of to a function that takes a map, but not a constructor?为什么我可以将 boost map_list_of 传递给一个接受地图而不是构造函数的函数?
【发布时间】:2015-12-29 19:54:06
【问题描述】:

我正在尝试构造一个将std::map 作为参数的对象,方法是使用boost map_list_of 将地图内容传递给它。

这会产生编译错误,但是,当我尝试对采用 std::map 的常规函数​​执行相同操作时,它编译得很好!

#include <map>
#include <boost/assign.hpp>

struct Blah
{
    Blah(std::map<int, int> data) {}
};

void makeBlah(std::map<int, int> data) {}

int main()
{
    Blah b(boost::assign::map_list_of(1, 2)(3, 4));    // Doesn't compile.

    makeBlah(boost::assign::map_list_of(1, 2)(3, 4));  // Compiles fine!
}

我得到的编译错误是:

error: call of overloaded ‘Blah(boost::assign_detail::generic_list<std::pair<int, int> >&)’ is ambiguous
note: candidates are: Blah::Blah(std::map<int, int, std::less<int>, std::allocator<std::pair<const int, int> > >)
note:                 Blah::Blah(const Blah&)

什么是歧义,它为什么不影响常规函数 makeBlah,据我所知,它与 Blah 构造函数具有相同的签名?

还有没有更好的方法来实现这一点,除了创建一个makeBlah 函数来构造Blah 的对象,就像我必须做的那样?

(顺便说一句,我在单元测试中使用map_list_of 执行此操作,以使测试输入数据的创建更具可读性)

【问题讨论】:

    标签: c++ boost constructor stl stdmap


    【解决方案1】:

    map_list_of 不会创建容器,但会创建一个

    可以转换为任何标准容器的匿名列表

    转换是通过模板用户定义的转换运算符完成的:

       template< class Container >
       operator Container() const; 
    

    因此在构造函数的上下文中,它无法推断是转换为map&lt;int, int&gt; 还是Blah。为了避免这种情况,例如,您可以添加一个虚拟构造函数参数:

    class Blah
    {
        public:
            Blah(std::map<int, int> data, int)
            {
            }
    
    };
    
    void makeBlah(std::map<int, int> data)
    {
    }
    
    void myTest()
    {
        Blah b(boost::assign::map_list_of(1, 2)(3, 4), 0);   
    
        makeBlah(boost::assign::map_list_of(1, 2)(3, 4));  
    }
    

    有了makeBlah,你就没有这样的歧义了。

    或者,您可以将列表类型作为构造函数参数,然后在Blah 中使用它:

    class Blah
    {
        public:
            Blah(decltype(boost::assign::map_list_of(0, 0)) data)
               : m(data.to_container(m))
            {
            }
    
        std::map<int, int> m;
    };
    

    【讨论】:

    • 虽然你可以使用decltype(),但你可以直接转储boost代码并使用initializer_list来初始化地图。
    【解决方案2】:

    自从 c++11 出现以来,boost::assign 变得不那么引人注目了。

    Blah b({{1, 2},{3, 4}});
    

    应该这样做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-20
      • 2020-09-06
      • 1970-01-01
      • 2022-12-11
      • 2016-11-27
      • 1970-01-01
      • 2016-03-03
      相关资源
      最近更新 更多