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::vector
overload (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