简体   繁体   English

用一个元素强制std :: vector重载而不是int重载

[英]Forcing std::vector overload instead of int overload on list with one element

Consider the code below: 考虑下面的代码:

#include <iostream>
#include <vector>

void f(std::vector<int> v) {std::cout << __PRETTY_FUNCTION__ << std::endl;}
void f(int n) {std::cout << __PRETTY_FUNCTION__ << std::endl;}

int main()
{
    f({42}); // the int overload is being picked up
}

Live on Coliru 住在科利鲁

I was a bit surprised to realize that in this case the int overload is being picked up, ie the output of the program is: 我很惊讶地意识到在这种情况下会接收到int重载,即程序的输出为:

void f(int) 无效f(int)

with the warning 带有警告

warning: braces around scalar initializer [-Wbraced-scalar-init] f({42}); 警告:标量初始值设定项[-Wbraced-scalar-init] f({42})括起来;

Of course this happens only when I pass a 1-element list as an argument, otherwise the std::vector overload is being picked up. 当然,只有当我将一个1元素列表作为参数传递时,才会发生这种情况,否则将拾取std::vector重载。

Why is {42} treated like a scalar and not like a init-list? 为什么{42}被视为标量而不是初始化列表? Is there any way of forcing the compiler to pick the std::vector overload (without explicitly constructing std::vector<int>{42} ) even on 1-element lists? 有没有办法强迫编译器选择std::vector重载(而没有显式构造std::vector<int>{42} )甚至在1元素列表上?

PS: The std::vector has an init-list constructor PS: std::vector具有init-list构造函数

vector(std::initializer_list<T> init, const Allocator& alloc = Allocator());

see (7) from cppreference . 请参阅cppreference中的 (7)。

Braced initializer has no type, we can't say {42} is an int or std::initializer_list<int> . 大括号初始化器没有类型,我们不能说{42}intstd::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) . {42}仅具有一个类型为int元素,则它与重载void f(int)完全匹配。 While for void f(std::vector<int>) a user-defined conversion is needed. 对于void f(std::vector<int>)需要用户定义的转换。 So void f(int) will be picked up here. 因此, void f(int)将在此处拾取。

Is there any way of forcing the compiler to pick the std::vector overload (without explicitly constructing std::vector<int>{42}) even on 1-element lists? 有没有办法强迫编译器选择std::vector重载(而无需显式构造std::vector<int>{42})甚至在1元素列表上?

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>) : 可以用一个大括号将编译器构造为std::initializer_list<int> ,然后选择void f(std::vector<int>)

f({{42}});

LIVE 生活

Forcing std::vector overload 强制std :: vector重载

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? 为什么不选择vector(initializer_list)构造函数?

Assume that another header declares a void f(std::set<int> v) . 假设另一个标头声明一个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 ? 您希望编译器在面对f({1})时如何作出反应:构造vector或构造set

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM