I'm trying to construct an object that takes a std::map
as a parameter, by passing it the map contents using boost map_list_of
.
This gives a compile error, however, when I try to do the same with a regular function that takes a std::map
, it compiles fine!
#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!
}
The compile error I get is:
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&)
What is the ambiguity, and how come it doesn't affect the regular functoin makeBlah, which as far as I can see, has the same signature as the Blah constructor?
And is there a better way of achieving this, short of making a makeBlah
function that will constructor an object of Blah
, as it looks like I will have to do?
(As an aside, I am doing this in a unit test using map_list_of
to make the test input data creation more readable)
map_list_of
doesn't create a container, but it creates an
anonymous list which can be converted to any standard container
The conversion is done through a template user-defined conversion operator:
template< class Container >
operator Container() const;
So in the context of the constructor, it cannot deduce whether to convert to the map<int, int>
or to Blah
. To avoid this, you can, for example, add a dummy constructor parameter:
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));
}
With the makeBlah
you don't have such an ambiguity.
Alternatively, you could take the list type as the constructor parameter and then use it within Blah
:
class Blah
{
public:
Blah(decltype(boost::assign::map_list_of(0, 0)) data)
: m(data.to_container(m))
{
}
std::map<int, int> m;
};
since the advent of c++11, boost::assign
has become less compelling than it was.
Blah b({{1, 2},{3, 4}});
should do it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With