考虑下面的代码:
#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
}
我有点惊讶地发现在这种情况下正在拾取 int 重载,即程序的输出是:
void f(int)
警告
warning: braces around scalar initializer [-Wbraced-scalar-init] f({42});
当然,只有当我将 1 元素列表作为参数传递时才会发生这种情况,否则 std::vector
正在拾取过载。
为什么是{42}
被视为标量而不是初始化列表?有没有办法强制编译器选择 std::vector
即使在 1 元素列表上也会重载(没有明确构造 std::vector<int>{42}
)?
附注:std::vector
有一个初始化列表构造函数
vector(std::initializer_list<T> init, const Allocator& alloc = Allocator());
参见 cppreference 中的 (7) .
最佳答案
大括号初始化器没有类型,我们不能说 {42}
是一个 int
或 std::initializer_list<int>
.当它用作参数时,special rules for overload resolution将应用于重载函数调用。
(强调我的)
- 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}
只有一个类型为 int
的元素, 那么它与重载 void f(int)
完全匹配.而对于 void f(std::vector<int>)
需要用户定义的转换。所以void f(int)
将在这里接走。
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?
换句话说,您可以放置额外的大括号来强制编译器构造一个 std::initializer_list<int>
然后拿起void f(std::vector<int>)
:
f({{42}});
关于c++ - 在具有一个元素的列表上强制 std::vector 重载而不是 int 重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46062730/