從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>
,其中列表初始化的細節表明將是第一個嘗試構造函數的類型?
要澄清一下''initializer_list''參數會導致'A(參數...)'中成功的模板參數推演。因此,我的CPP報價的第一行(轉換爲'initialiser_list'參數)適用於查找候選非模板構造函數,而您的報價適用於使用模板參數推導查找候選模板函數。如果模板或非模板函數都不提供合適的候選,則每個列表元素都被視爲單獨的參數。 –
AntiElephant
在** [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;'編譯。我不知道爲什麼。 –
啊。 ** [temp.deduct.call]/1 **談論參數是一個初始化列表(也就是用逗號分隔的一系列逗號分隔值),而不是'std :: initializer_list'的實例。區別很重要,兩者不可互換。 –