给予
struct E
{
};
struct P
{
explicit P(E) {}
};
struct L
{
operator E() {return {};}
operator P() {return P{E{}};}
};
根据C ++ 17语言标准,表达式P{L{}}
是否可以编译?
不同的编译器产生不同的结果:
答案 0 :(得分:4)
我认为每个标准的正确行为都是模棱两可的。
如果初始化程序是一个(非括号括起来的)braced-init-list或= braced-init-list,则该对象或引用将被列表初始化。
否则,如果T是类类型,则考虑构造函数。枚举适用的构造函数,并通过重载解析([over.match],[over.match.list])选择最佳的构造函数。如果要转换任何参数都需要缩小转换(请参见下文),则程序格式错误。
[over.match.list]仅涉及选择构造函数。我们有两个可行的选择:通过P(E)
使用L{}.operator E()
和通过P(P&&)
使用L{}.operator P()
(隐式移动构造函数)。另一个没有更好的选择。
但是,这很让人联想到CWG 2327:
struct Cat {}; struct Dog { operator Cat(); }; Dog d; Cat c(d);
该问题表明当前调用Cat(Cat&&)
而不只是d.operator Cat()
,并建议我们实际上也应该考虑转换函数。但这仍然是一个未解决的问题。我不确定gcc或clang针对此问题(或针对首先提出的类似示例)做了什么,但是根据您的结果,我怀疑他们认为直接转换函数L{}.operator P()
是更好的匹配,然后这样做。