c++ - 在具有一个元素的列表上强制 std::vector 重载而不是 int 重载

标签 c++ c++11 vector overloading initializer-list

考虑下面的代码:

#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 重载,即程序的输出是:

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}是一个 intstd::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}});

LIVE

关于c++ - 在具有一个元素的列表上强制 std::vector 重载而不是 int 重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40167012/

相关文章:

c++ - 即使无处调用模板函数,static_assert 也会编译失败

c++ - 当前缀字符串与非前缀字符串相邻时,字符串文字连接失败?

c++ - 撤消/重做时释放内存时出现问题

C++从文本文件中读取并分离成 vector

vector - 为什么 borrow checker 提示这些不同切片的生命周期?

c++ - 使用动态规划打印矩阵中所有可能路径中总和最小的路径

c++ - 运算符删除导致堆损坏,而运算符新工作正常

c++ - 将 1D 转换为 2D?

c# - C#和C++之间的进程间通信

c++ - std::unordered_map 的递增迭代器