使用一个元素

时间:2016-10-21 01:35:17

标签: 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)

带警告

  

警告:标量初始化器周围的大括号[-Wbraced-scalar-init] f({42});

当然,只有当我将1元素列表作为参数传递时才会发生这种情况,否则会发现std::vector重载。

为什么{42}被视为标量而不是初始列表?有没有办法迫使编译器选择std::vector重载(没有明确构建std::vector<int>{42}),即使在单元素列表上也是如此?

PS:std::vector有一个init-list构造函数

vector(std::initializer_list<T> init, const Allocator& alloc = Allocator());

cppreference中的(7)。

2 个答案:

答案 0 :(得分:6)

支持初始化程序没有类型,我们不能说{42}intstd::initializer_list<int>。当它用作参数时,special rules for overload resolution将应用于重载函数调用。

(强调我的)

  
      
  • 否则,如果参数类型不是类且初始化列表有一个元素,则隐式转换序列是将元素转换为参数类型
  •   

{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

答案 1 :(得分:1)

强制std :: vector重载

int main()
{
    f(std::vector<int>{42}); // the vector overload is being picked up now
}

为什么vector(initializer_list)构造函数没有被选中?

假设另一个标头声明void f(std::set<int> v)

您希望编译器在面对f({1})时做出反应:构建vector还是构建set