2017-03-05 41 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。

相關問題