考虑下面的代码:
#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
我有点惊讶地意识到在这种情况下 int 重载被拾取,即程序的输出是:
无效 f(int)
与警告
警告:标量初始值设定项周围有大括号 [-Wbraced-scalar-init] f({42});
当然,只有当我传递一个 1 元素列表作为参数时,才会发生这种情况,否则std::vector
超载正在恢复。
Why is {42}
被视为标量而不是初始化列表?有没有办法强制编译器选择std::vector
重载(没有显式构造std::vector<int>{42}
)甚至在一元素列表上?
PS: The std::vector
有一个 init-list 构造函数
vector(std::initializer_list<T> init, const Allocator& alloc = Allocator());
参见(7)参考参数.
大括号初始化器没有类型,我们不能说{42}
is an int
or std::initializer_list<int>
。当它被用作参数时,重载解析的特殊规则将应用于重载函数调用。
(强调我的)
- 否则,如果参数类型不是类并且初始化列表有一个元素,隐式转换序列是所需的序列将元素转换为参数类型
{42}
只有一个元素具有类型int
,那么它与过载完全匹配void f(int)
。而对于void f(std::vector<int>)
需要用户定义的转换。所以void f(int)
将会在这里被接走。
有没有办法强制编译器选择std::vector
重载(没有显式构造std::vector<int>{42})
即使在一元素列表上?
简而言之,您可以添加额外的大括号来强制编译器构造一个std::initializer_list<int>
然后拿起void f(std::vector<int>)
:
f({{42}});
LIVE
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)