2017-03-05 108 views
1

在下面的代码中,对于两个版本的print方法,第一个调用将解析为initializer_list。如果我用initializer_list注释掉这个定义,程序会无缝地使用矢量版本。在第一种情况下,我期待编译器抱怨!编译器如何在vector和initializer_list之间做出决定?

#include <iostream> 
#include <vector> 
using namespace std; 

void print(const vector<int>& v1){ 
     cout << "vector \n"; 
} 
void print(const initializer_list<int>& il) { 
     cout << "init list \n"; 
} 

int main() { 
     print({1,2,3,4,5}); 
     return 0; 
} 
+0

这就是重载解析在C++中的工作原理。 – 101010

回答

1

这是如何在C++中工作的overload resolution。两种版本的print都适用于重载分辨率。

  • print(const vector<int>& v1)是重载一个可行的功能,因为在来电者输入初始化列表{1,2,3,4,5}隐式转换为一个std::vector<int>
  • print(const initializer_list<int>& il)是一个重载解析的可行函数,使得调用者的输入类型完美匹配。

当两个重载都发挥print(const initializer_list<int>& il)被选为最佳可行函数因为它是一个完美的匹配和完美匹配具有过载分辨率比的隐式转换更高的优先级。

0

重载解析通过表达将参数转换为参数类型所需的操作,作为转换序列,然后根据一些规则对转换序列进行排序。

因为我们正在初始化的引用,[over.ics.ref]/2采用:

当引用类型的参数不直接结合到一个参数表达式,转换序列是需要将一个根据13.3.3.1将参数表达式转换为参考的基础类型。从概念上讲,该转换序列对应于使用参数表达式复制初始化基础类型的临时文件。顶层cv-qualification中的任何差异都包含在初始化本身中,并不构成转换。

因此,这可以让我们如同代码是使用相同的转换序列规则:

void o_print(initializer_list<int> ol); 
void o_print(vector<int> o1); 

即非const对象作为参数,而不是常量引用。

目前:

  • 根据[over.ics.list]/2,intstd::initializer_list<int>一个支撑列表的转换是标识转换。 (如果列表成员需要升级或转换为int,则不会这样)。

  • 根据[over.ics.list/4时,转换一个支撑列表以非聚合类(std::vector<int>这里)的过载分辨率选择的std::vector一个构造,并且该序列被定义为用户定义的转换序列

最后我们准备好现在应用排名规则。身份转换排名高于用户定义的转换顺序,因此initializer_list<int>版本获胜。

注意:所有引用都是C++ 14。

相关问题