为什么我可以将boost map_list_of传递给接受map而不是构造函数的函数?



我试图构建一个以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的单元测试中这样做的,以使测试输入数据的创建更具可读性)

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

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

通过模板用户定义的转换操作符完成转换:

   template< class Container >
   operator Container() const; 

因此,在构造函数的上下文中,它不能推断是转换为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));  
}

有了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;
};

自从c++11出现以来,boost::assign已经不再像以前那么引人注目了。

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

最新更新