c++pointersinitializer-listoverload-resolutionnullptr

Overload resolution of a pointer and a container with pointers


I wrote a function with two overloads - one for a single pointer and one for a vector of pointers. At some point in the code I wanted to pass an empty vector to the function and used {} as the argument.

#include <vector>
#include <iostream>

void f(std::vector<const int*> v)
{
    std::cout << "vector overload" << std::endl;
}
 
void f(const int* i)
{
    std::cout << "pointer overload" << std::endl;
}

int main()
{
    f({});
    return 0;
}

Unfortunately, this will not call the vector overload with an empty vector but the pointer overload with a nullptr.

The solution to the problem was to replace the pointer overload with a reference, which can't be initialised with {}.

void f(const int& i);

Why doesn't the compiler complain about an ambiguous call? Why does it prefer the pointer overload?


Solution

  • Because the conversion from braced-list to std::vector is classified as user-defined conversion sequence, which has lower rank.

    You can add another overload taking std::initializer_list which will be preferred. E.g.

    void f(std::initializer_list<const int*> v)
    {
        f(std::vector<const int*>(v)); // forward to the overload taking std::vector
    }
    

    LIVE