为什么我可以将boost map_list_of传递给采用地图但不是构造函数的函数?

nap*_*con 8 c++ constructor boost stl stdmap

我正在尝试std::map通过使用boost传递地图内容来构造一个以参数为参数的对象map_list_of.

这给出了编译错误,但是,当我尝试使用带有a的常规函数​​执行相同操作时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!
}
Run Code Online (Sandbox Code Playgroud)

我得到的编译错误是:

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&)
Run Code Online (Sandbox Code Playgroud)

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

有没有更好的方法来实现这一点,而不是制作一个makeBlah将构造函数作为对象的函数Blah,因为它看起来像我将要做的那样?

(顺便说一下,我在单元测试中这样做,map_list_of用于使测试输入数据创建更具可读性)

Ros*_*lav 5

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

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

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

   template< class Container >
   operator Container() const; 
Run Code Online (Sandbox Code Playgroud)

所以在构造函数的上下文中,它无法推断是否转换为map<int, int>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));  
}
Run Code Online (Sandbox Code Playgroud)

随着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;
};
Run Code Online (Sandbox Code Playgroud)