2015-11-26 141 views
3

CPP reference在列表初始化:列表,初始化和可變參數的構造函數

否則,T的構造都認爲,在兩個階段:

  • 稱取所有的std ::構造initializer_list作爲唯一的參數,或作爲第一個參數,如果其餘參數具有默認值,將被檢查,並通過重載解析匹配類型爲std的單個參數:initializer_list

  • 如果前一階段沒有產生匹配,則T的所有構造函數都參與重載解析,該重載解決方法針對由braced-init-list的元素組成的參數集,限制條件是隻允許非縮小轉換。如果這個階段產生一個明確的構造函數的副本列表初始化的最佳匹配,編譯失敗(注,在簡單的複製初始化,顯式的構造不考慮在所有)

因此,一個構造函數首先考慮使用initializer_list。否則,列表中的每個元素都將被視爲構造函數的參數。然而

#include <iostream> 

using namespace std; 

struct A{ 
    template <typename... Args> A(Args... li) { cout << sizeof...(Args) << endl;} 
}; 

int main(){ 

    A a = {2,3,4}; 

} 

輸出是3這表明Args...解包爲int, int, int。爲什麼Args ...不是簡單地做成單數initializer_list<int>,其中列表初始化的細節表明將是第一個嘗試構造函數的類型?

回答

4

[temp.deduct.call]/1模板參數推導由每個功能模板參數類型比較完成與所述呼叫的相應參數的類型(稱爲P)(稱之爲A)作爲如下面所描述的。如果從P中刪除引用和cv-限定符給出std::initializer_list<P'>對於某些P'並且參數是初始化符列表(8.5.4),則對初始化符列表的每個元素執行推導,取P'作爲函數模板參數類型,然後初始化元素作爲其參數。否則,初始化程序列表參數會導致該參數被視爲未推導的上下文(14.8.2.5)。

強調我的。因此,從initializer_list<int>類型的參數構造函數的模板參數推演失敗。

+0

要澄清一下''initializer_list ''參數會導致'A(參數...)'中成功的模板參數推演。因此,我的CPP報價的第一行(轉換爲'initialiser_list'參數)適用於查找候選非模板構造函數,而您的報價適用於使用模板參數推導查找候選模板函數。如果模板或非模板函數都不提供合適的候選,則每個列表元素都被視爲單獨的參數。 – AntiElephant

+0

在** [dcl.init.list]/2 **中有一個註釋:「將一個初始化程序列表作爲參數傳遞給構造函數模板'template C(T)'的類'C'不會創建一個初始化程序-list構造函數,因爲初始化程序列表參數會導致相應的參數成爲非推導的上下文(14.8.2.1)。「這就是我導致** [temp.deduct.call] **的原因。現在,將程序中的'main'改爲'std :: initializer_list l {2,3,4}; a a = 1;'編譯。我不知道爲什麼。 –

+0

啊。 ** [temp.deduct.call]/1 **談論參數是一個初始化列表(也就是用逗號分隔的一系列逗號分隔值),而不是'std :: initializer_list'的實例。區別很重要,兩者不可互換。 –

1

如果您明確提供了一個帶有std::initializer_list的構造函數,則應該選擇: Demo

template <typename... Args> A(Args...)不是第一個參數爲std::initializer_list的構造函數(即使第一個參數可能是std::initializer_list)。

而在A a = {2, 3, 4},{2, 3, 4}沒有類型。它不是std::initializer_list

相關問題