问题
Consider the following example code:
Example:
void print(int n) {
cout << "element print\n";
}
void print(vector<int> vec) {
cout << "vector print\n";
}
int main() {
/* call 1 */ print(2);
/* call 2 */ print({2});
std::vector<int> v = {2};
/* call 3 */ print(v);
/* call 4 */ print( std::vector<int>{2} );
return 0;
}
which generates the following output:
element print
element print
vector print
vector print
Why the call to print function (call 2 in above example) is getting matched to function accepting a single value? I am creating a vector (containing a single element) in this call, so should it not match to call to print with vector as input?
This is partially discussed in an other question where the provided solution works for vectors with more than 1 elements.
回答1:
Because the 1st overload wins in the overload resolution for print({2});.
In both cases copy list initialization applies, for the 1st overload taking int,
(emphasis mine)
Otherwise (if
Tis not a class type), if the braced-init-list has only one element and eitherTisn't a reference type or is a reference type that is compatible with the type of the element,Tis direct-initialized (in direct-list-initialization) or copy-initialized (in copy-list-initialization), except that narrowing conversions are not allowed.
{2} has only one element, it could be used to initialize an int as the argument directly; this is an exact match.
For the 2nd overload taking std::vector<int>,
Otherwise, the constructors of
Tare considered, in two phases:
- All constructors that take
std::initializer_listas the only argument, or as the first argument if the remaining arguments have default values, are examined, and matched by overload resolution against a single argument of typestd::initializer_list
That means an std::initializer_list<int> is constructed and used as the constructor's argument of std::vector<int> (to construct the argument for print). One user-defined conversion (via the constructor of std::vector taking one std::initializer_list) is required, then it's worse match than the 1st overload.
回答2:
{2} is a legal initializer for a number of types, including int. Overload resolution prefers a type that exactly matches to one that requires further construction.
回答3:
No thats not what you do, you`re creating an initializer_list.
See: http://en.cppreference.com/w/cpp/utility/initializer_list
Call 1) Single Element is called
Call 2) initializer_list creates an single int element
Call 3) A Vector object is given
Call 4) A Vector object is given
The Overload resulotion prefers to use the int parameter method before the std::vector parameter method, because there are less type conversions. The int parameter is a direct match, for the vector parameter an additional conversion is needed.
For example:
void print(std::initializer_list<int> list){
cout << "initializer_list print\n";
}
would result for call 2, that the output is "initializer_list print"
来源:https://stackoverflow.com/questions/46565165/single-element-vector-initialization-in-a-function-call