在具有一个元素的列表上强制 std::vector 重载而不是 int 重载
Forcing std::vector overload instead of int overload on list with one element
考虑以下代码:
#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
重载(无需显式构造 std::vector<int>{42}
),即使是在 1 元素列表上?
PS: std::vector
有一个初始化列表构造函数
vector(std::initializer_list<T> init, const Allocator& alloc = Allocator());
参见 cppreference 中的 (7)。
强制std::vector过载
int main()
{
f(std::vector<int>{42}); // the vector overload is being picked up now
}
为什么 vector(initializer_list)
构造函数没有被拾取?
假设另一个 header 声明了一个 void f(std::set<int> v)
。
您希望编译器在遇到 f({1})
时如何反应:构造一个 vector
还是构造一个 set
?
大括号初始化器没有类型,我们不能说 {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 constructing std::vector<int>{42})
even on 1-element lists?
作为一种变通方法,您可以添加额外的大括号以强制编译器构造一个 std::initializer_list<int>
然后选择 void f(std::vector<int>)
:
f({{42}});
考虑以下代码:
#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
重载(无需显式构造 std::vector<int>{42}
),即使是在 1 元素列表上?
PS: std::vector
有一个初始化列表构造函数
vector(std::initializer_list<T> init, const Allocator& alloc = Allocator());
参见 cppreference 中的 (7)。
强制std::vector过载
int main()
{
f(std::vector<int>{42}); // the vector overload is being picked up now
}
为什么 vector(initializer_list)
构造函数没有被拾取?
假设另一个 header 声明了一个 void f(std::set<int> v)
。
您希望编译器在遇到 f({1})
时如何反应:构造一个 vector
还是构造一个 set
?
大括号初始化器没有类型,我们不能说 {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}});