Search code examples
c++templatesambiguous

Call to variadic template is ambigous


I have a variadic template function that works except if I call it with an argument of the same type as T.

template <typename T, typename... Arg>
std::shared_ptr<T> make_shared(Arg&&... arg)
{
    return std::shared_ptr<T>(new T(std::forward<Arg>(arg)...));
}

Working call:

auto sahredStr = make_shared<std::string>("fubar"); 

Ambigous call:

std::string str = "fubar";
auto sharedStr = make_shared<std::string>(str);  

I would like to understand what is wrong with the second call.

LIVE DEMO


Solution

  • For a call to a function using an unqualified name, the name lookup procedure also considers namespaces that the types of arguments (and type template arguments thereof) are declared in - also known as Argument Dependent Lookup. For a std::string-typed argument, this means that the make_shared function is also searched for in the std namespace. As such, the set of viable overloads includes also the std::make_shared function, hence ambiguity.

    A solution is to either change the name of your function to avoid conflicts with the std's overload, or wrap the function name with parenthesis:

    auto sharedStr = (make_shared<std::string>)(str);
    //              ~^~                      ~^~