Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function overloading with initialization_list causing ambiguity

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

  1. I tried with VS2013 as well as g++ and both of them errors out.
  2. As per @chris the above code compiles in clang
  3. What does the standard say? Or does it actually say anything?
like image 674
Abhijit Avatar asked Feb 24 '26 06:02

Abhijit


1 Answers

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.

like image 50
Mike Seymour Avatar answered Feb 25 '26 18:02

Mike Seymour