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/46062730/

相关文章:

c++ - 由于具有循环引用的类中的 unique_ptr 或 vector 而导致核心转储

c++ - vector的第一个元素的地址是固定的吗?

在 R 中读取和绘制 esri 形状文件

c++ - 在析构函数中删除指针时崩溃

python - 在匹配另一个模式的字符串中找到最短子串的开始和结束索引

C++ 将 For 循环的输出分配给变量

c++ - std::random_device 加密安全吗?

c++ - 迭代循环和 lambda 函数

c++ - 返回一个指向智能指针的原始指针

c++ - 转换字符串 vector : skip elements based on the previous value