Consider the code below:
#include
#include
void f(std::vector v) {std::cout << __PRETTY_FUNCTION__ <<
Forcing std::vector overload
int main()
{
f(std::vector<int>{42}); // the vector overload is being picked up now
}
Why isn't the vector(initializer_list) constructor being picked up?
Assume that another header declares a void f(std::set<int> v).
How would you like the compiler to react when faced with f({1}): construct a vector or construct a set?
Braced initializer has no type, we can't say {42} is an int or std::initializer_list<int>. When it's used as an argument, special rules for overload resolution will be applied for overloaded function call.
(emphasis mine)
- Otherwise, if the parameter type is not a class and the initializer list has one element, the implicit conversion sequence is the one required to convert the element to the parameter type
{42} has only one element with type int, then it's exact match for the overload void f(int). While for void f(std::vector<int>) a user-defined conversion is needed. So void f(int) will be picked up here.
Is there any way of forcing the compiler to pick the
std::vectoroverload (without explicitly constructingstd::vector<int>{42})even on 1-element lists?
As a wordaround, you can put additional braces to force the compiler construct a std::initializer_list<int> and then pick up void f(std::vector<int>):
f({{42}});
LIVE