编译器如何在向量vs Initializer_list之间做出决定



在下面的代码中,两种版本的打印方法都会呈现第一个呼叫解散给使用initializer_list的呼叫。如果我使用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;
}

这是过载分辨率在C 中工作的方式。print的两个版本对于超载分辨率都可行。

  • print(const vector<int>& v1)是过载分辨率的可行函数,因为呼叫者中的输入初始化器列表{1,2,3,4,5}隐式转换为std::vector<int>
  • print(const initializer_list<int>& il)是超载分辨率的可行函数,导致呼叫者中的输入类型完全匹配。

当两个过载都播放到play时,选择print(const initializer_list<int>& il)作为最佳的可行函数,因为它是完美的匹配,而完美的匹配在过载分辨率方面比隐式转换更优先。

过载分辨率可以通过将参数转换为a conversion序列将参数转换为参数类型所需的操作,然后根据某些规则对转换序列进行排名。

由于我们正在初始化参考文献,因此[over.ics.ref]/2适用:

当参考类型的参数不直接绑定到参数表达式时,转换序列是根据13.3.3.1将参数表达式转换为参考的基础类型所需的序列。从概念上讲,此转换序列对应于带有参数表达式的基础类型的临时性化。顶级CV资格的任何差异都取决于初始化本身,并且不构成转换。

因此,这使我们可以使用相同的转换序列规则,就像代码为:

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

即。将非const对象作为参数而不是const引用。

现在:

  • 根据[over.ics.list]/2,将int的支撑列表转换为 std::initializer_list<int> IDENS conversion 。(不是列表成员需要晋升或转换为int)。

  • 根据[over.ics.list]/4,将支撑列表转换为非聚集类(std::vector<int>这里)通过超载分辨率选择std::vector的构造函数,并且此序列定义为A 用户定义的转换序列

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

nb。所有参考都是指C 14。

最新更新