函数调用中的单元素向量初始化

2021-12-21 00:00:00 vector c++ c++11 stl overload-resolution

考虑以下示例代码:

示例:

void print(int n) {
    cout << "element print
";
}

void print(vector<int> vec) {
    cout << "vector print
";
}

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

生成以下输出:

element print
element print
vector print
vector print

为什么对 print 函数的调用(上例中的调用 2)与接受单个值的函数匹配?我在这个调用中创建了一个向量(包含一个元素),所以它应该不匹配以向量作为输入调用 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?

这是部分讨论的在另一个问题中提供的解决方案适用于具有 1 个以上元素的向量.

This is partially discussed in an other question where the provided solution works for vectors with more than 1 elements.

推荐答案

因为第一个重载在 print({2}); 的重载决议中获胜.

Because the 1st overload wins in the overload resolution for print({2});.

在这两种情况下复制列表初始化都适用,对于第一个重载<代码>int,

In both cases copy list initialization applies, for the 1st overload taking int,

(强调我的)

否则(如果 T 不是类类型),如果花括号初始化列表只有一个元素并且 T 不是'不是引用类型或者是与元素类型兼容的引用类型,T 是直接初始化(在直接列表初始化中)或复制初始化(在复制列表中)初始化),除了不允许缩小转换.

Otherwise (if T is not a class type), if the braced-init-list has only one element and either T isn't a reference type or is a reference type that is compatible with the type of the element, T is direct-initialized (in direct-list-initialization) or copy-initialized (in copy-list-initialization), except that narrowing conversions are not allowed.

{2} 只有一个元素,可以直接初始化一个int作为参数;这是完全匹配.

{2} has only one element, it could be used to initialize an int as the argument directly; this is an exact match.

对于采用 std::vector 的第二次重载,

For the 2nd overload taking std::vector<int>,

否则,分两个阶段考虑T的构造函数:

Otherwise, the constructors of T are considered, in two phases:

  • 所有将 std::initializer_list 作为唯一参数或作为第一个参数(如果其余参数具有默认值)的构造函数都被检查,并通过重载决议与类型的单个参数进行匹配std::initializer_list
  • All constructors that take std::initializer_list as 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 type std::initializer_list

这意味着 std::initializer_list 被构造并用作 std::vector 的构造函数参数(构造 std::vector 的参数代码>打印).需要一个用户定义的转换(通过 std::vector 的构造函数获取一个 std::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.

相关文章