I am trying to overload function with initialization_list as parameters with variation to accept map and vector along with an integer. The compiler complains that the function resolution is ambiguous. I am wondering what causes the ambiguity and how to resolve it
#include <memory>
#include <iostream>
#include <map>
#include <initializer_list>
std::shared_ptr<int> foo(const std::initializer_list<std::pair<const std::string, std::shared_ptr<int> > >& il)
{
return std::make_shared<int>();
}
std::shared_ptr<int> foo(const std::initializer_list<std::shared_ptr<int> > & il)
{
return std::make_shared<int>();
}
std::shared_ptr<int> foo(int num)
{
return std::make_shared<int>();
}
int main()
{
foo({ { "a", foo(10) } });
}
Try It OUT >>>
Note
what causes the ambiguity
shared_ptr has a constructor with two arguments:
template<class Y, class D> shared_ptr(Y* p, D d);
which matches the initialiser list { "a", foo(10) } as well as a pair does. (Or, if not as well, then close enough for some compilers to get it wrong. The exact rules melt my brain, so I won't try to figure out which compiler is technically correct.)
how to resolve it
Assuming you want the first overload, provide a pair type, rather than a more general initialiser list:
foo({ std::make_pair( "a", foo(10) ) });
What does the standard say? Or does it actually say anything?
It says a lot, often in rather opaque language. I can't quote the twenty pages of [over.match], and don't have the language-lawyer skills to summarise how they apply here while retaining my sanity.
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