从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'的实例。区别很重要,两者不可互换。 –