直接列表初始化编译成功,但是正常的直接初始化失败,为什么?
Direct list initialization compiles successfully, but normal direct initialization fails, why?
例如,代码如下:
struct A { A(int); };
struct B { B(A); };
int main()
{
B b{{0}}; // OK
B c({0}); // error
}
错误信息是:
f.cc: In function 'int main()':
f.cc:7:9: error: call of overloaded 'B(<brace-enclosed initializer list>)' is ambiguous
B c({0}); // error
^
f.cc:7:9: note: candidates are:
f.cc:2:12: note: B::B(A)
struct B { B(A); };
^
f.cc:2:8: note: constexpr B::B(const B&)
struct B { B(A); };
^
f.cc:2:8: note: constexpr B::B(B&&)
截至最新的官方标准C++14,您的第一次初始化没有歧义。 [over.match.list]:
由于不存在初始化列表构造函数,我们输入 "second phase"。现在考虑 [over.best.ics]/4:
我们的元素是{0}
。因此这不允许复制构造函数的(用户定义的)转换{0}
-> A
。显然,如果我们不在 [over.match.list] 的第二阶段,这不适用,因此对于 B c({0})
的示例,c
和两个构造函数都不会发生列表初始化被考虑。
CWG 问题 1467
第一次初始化目前与第二次初始化一样不明确。编译器还没有实现 CWG #1467 - 它的决议删除了上面引用的要点 (4.5)。
请参阅 #2076,它选择还原更改:
The resolution of issue 1467 made some plausible constructs
ill-formed. For example,
struct A { A(int); };
struct B { B(A); };
B b{{0}};
This is now ambiguous, because the text disallowing user-defined
conversions for B
's copy and move constructors was removed from
13.3.3.1 [over.best.ics] paragraph 4.
"The text" 是前面提到的要点。理查德史密斯提出以下措辞:
For non-class types, we allow initialization from a single-item list
to perform a copy only if the element within the list is not itself a
list (13.3.3.1.5 [over.ics.list] bullet 9.1). The analogous rule for
this case would be to add back the bullet in 13.3.3.1 [over.best.ics]
paragraph 4, but only in the case where the initializer is itself an
initializer list:
the second phase of
13.3.1.7 [over.match.list] when the initializer list has exactly one element that is
itself an initializer list, where the target is the first parameter of
a constructor
of class X
, and the conversion is
to X
or reference to (possibly cv-qualified) X
,
因为初始化器 {0}
本身就是一个初始化器列表,所以该要点将使您的第一个初始化再次合式。
例如,代码如下:
struct A { A(int); };
struct B { B(A); };
int main()
{
B b{{0}}; // OK
B c({0}); // error
}
错误信息是:
f.cc: In function 'int main()':
f.cc:7:9: error: call of overloaded 'B(<brace-enclosed initializer list>)' is ambiguous
B c({0}); // error
^
f.cc:7:9: note: candidates are:
f.cc:2:12: note: B::B(A)
struct B { B(A); };
^
f.cc:2:8: note: constexpr B::B(const B&)
struct B { B(A); };
^
f.cc:2:8: note: constexpr B::B(B&&)
截至最新的官方标准C++14,您的第一次初始化没有歧义。 [over.match.list]:
由于不存在初始化列表构造函数,我们输入 "second phase"。现在考虑 [over.best.ics]/4:
我们的元素是{0}
。因此这不允许复制构造函数的(用户定义的)转换{0}
-> A
。显然,如果我们不在 [over.match.list] 的第二阶段,这不适用,因此对于 B c({0})
的示例,c
和两个构造函数都不会发生列表初始化被考虑。
CWG 问题 1467
第一次初始化目前与第二次初始化一样不明确。编译器还没有实现 CWG #1467 - 它的决议删除了上面引用的要点 (4.5)。
请参阅 #2076,它选择还原更改:
The resolution of issue 1467 made some plausible constructs ill-formed. For example,
struct A { A(int); }; struct B { B(A); }; B b{{0}};
This is now ambiguous, because the text disallowing user-defined conversions for
B
's copy and move constructors was removed from 13.3.3.1 [over.best.ics] paragraph 4.
"The text" 是前面提到的要点。理查德史密斯提出以下措辞:
For non-class types, we allow initialization from a single-item list to perform a copy only if the element within the list is not itself a list (13.3.3.1.5 [over.ics.list] bullet 9.1). The analogous rule for this case would be to add back the bullet in 13.3.3.1 [over.best.ics] paragraph 4, but only in the case where the initializer is itself an initializer list:
the second phase of 13.3.1.7 [over.match.list] when the initializer list has exactly one element that is itself an initializer list, where the target is the first parameter of a constructor
of classX
, and the conversion is toX
or reference to (possibly cv-qualified)X
,
因为初始化器 {0}
本身就是一个初始化器列表,所以该要点将使您的第一个初始化再次合式。