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?
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
}