[英]List-initializer and variadic constructor
From CPP reference on list-initialisation: 从CPP参考列表初始化:
Otherwise, the constructors of T are considered, in two phases:
否则,T的构造函数分为两个阶段:
All constructors that take std::initializer_list as the only argument, or as the first argument if the remaining arguments have default values, are examined, and matched by overload resolution against a single argument of type std::initializer_list
将std :: initializer_list作为唯一参数的所有构造函数,或作为第一个参数,如果其余参数具有默认值,将检查所有构造函数,并通过重载决策与std :: initializer_list类型的单个参数进行匹配
If the previous stage does not produce a match, all constructors of T participate in overload resolution against the set of arguments that consists of the elements of the braced-init-list, with the restriction that only non-narrowing conversions are allowed.
如果前一个阶段没有产生匹配,则T的所有构造函数都参与对由braced-init-list元素组成的参数集的重载解析,并限制只允许非缩小转换。 If this stage produces an explicit constructor as the best match for a copy-list-initialization, compilation fails (note, in simple copy-initialization, explicit constructors are not considered at all)
如果此阶段产生显式构造函数作为复制列表初始化的最佳匹配,则编译失败(注意,在简单的复制初始化中,根本不考虑显式构造函数)
So a constructor using initializer_list
is considered first. 因此首先考虑使用
initializer_list
的构造initializer_list
。 Failing that, each element of the list is considered as arguments for constructors. 如果做不到这一点,列表的每个元素都被视为构造函数的参数。 However
然而
#include <iostream>
using namespace std;
struct A{
template <typename... Args> A(Args... li) { cout << sizeof...(Args) << endl;}
};
int main(){
A a = {2,3,4};
}
The output is 3
which indicates that Args...
unpacks as int, int, int
. 输出为
3
,表示Args...
解包为int, int, int
。 Why is it that Args... was not simply made the singular initializer_list<int>
, which the details on list-initialisation indicated would be the first attempted type of constructor? 为什么Args ...不是简单地创建了单数的
initializer_list<int>
,list-initialisation指出的细节是第一个尝试类型的构造函数?
[temp.deduct.call]/1 Template argument deduction is done by comparing each function template parameter type (call it
P
) with the type of the corresponding argument of the call (call itA
) as described below.[temp.deduct.call] / 1模板参数推导是通过将每个函数模板参数类型(称之为
P
)与调用的相应参数的类型(称为A
)进行比较来完成的,如下所述。 If removing references and cv-qualifiers fromP
givesstd::initializer_list<P'>
for someP'
and the argument is an initializer list (8.5.4), then deduction is performed instead for each element of the initializer list, takingP'
as a function template parameter type and the initializer element as its argument.如果从
P
删除引用和cv限定符,则为某些P'
提供std::initializer_list<P'>
,并且参数是初始化列表(8.5.4),然后对初始化列表的每个元素执行推导,取P'
作为函数模板参数类型,初始化元素作为参数。 Otherwise, an initializer list argument causes the parameter to be considered a non-deduced context (14.8.2.5).否则, 初始化列表参数会将参数视为非推导上下文(14.8.2.5)。
Emphasis mine. 强调我的。 For this reason, template argument deduction for the constructor from an argument of type
initializer_list<int>
fails. 因此,类型为
initializer_list<int>
的参数的构造函数的模板参数推断失败。
If you provide explicitly a constructor with std::initializer_list
, it would be choose: Demo . 如果使用
std::initializer_list
显式提供构造std::initializer_list
,则选择: Demo 。
template <typename... Args> A(Args...)
is not a constructor with first argument std::initializer_list
(even if first argument may be an std::initializer_list
). template <typename... Args> A(Args...)
不是第一个参数std::initializer_list
的构造std::initializer_list
(即使第一个参数可能是std::initializer_list
)。
And in A a = {2, 3, 4}
, {2, 3, 4}
has no type. 在
A a = {2, 3, 4}
, {2, 3, 4}
没有类型。 It is not a std::initializer_list
. 它不是
std::initializer_list
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.