jac*_*k X 8 c++ language-lawyer c++20
考虑这个例子
\n#include <iostream>\nstruct T{\n T() = default;\n T(T const&) =default;\n};\nT global;\nstruct S{\n operator T(){\n std::cout<<"#1\\n";\n return T{};\n }\n operator T&(){\n std::cout<<"#2\\n"; \n return global;\n }\n};\n\nint main(){\n S s;\n T obj(s);\n}\nRun Code Online (Sandbox Code Playgroud)\nGCC 选择#1,而 Clang 选择#2,相反,我认为它们不明确。根据dcl.init#17.6.3
\n\n\n否则(即,对于其余的复制初始化情况),可以从源类型转换为目标类型或(当使用转换函数时)转换为其派生类的用户定义转换如[over. match.copy],并通过重载决策 ([over.match]) 选择最好的一个。如果转换无法完成或不明确,则初始化格式错误。使用初始值设定项表达式作为其参数来调用所选函数;如果函数是构造函数,则调用是目标类型的 cv 无限定版本的纯右值,其结果对象由构造函数初始化。该调用用于根据上述规则直接初始化作为复制初始化目标的对象。
\n
\n\n当初始化表达式的类型是类类型 \xe2\x80\x9ccv S\xe2\x80\x9d 时,考虑 S 及其基类的非显式转换函数。初始化临时对象 ([class.mem]) 时,该对象将绑定到构造函数的第一个参数,其中该参数的类型为 \xe2\x80\x9c,引用 cv2 T\xe2\x80\x9d,并且使用在直接初始化 \xe2\x80\x9ccv3 T\xe2\x80\x9d 类型的对象的上下文中的单个参数,还考虑显式转换函数。那些未隐藏在 S 中并产生 cv 未限定版本与 T 类型相同或其派生类的类型的函数是候选函数。对返回 \xe2\x80\x9creference 到 X\xe2\x80\x9d 的转换函数的调用是 X 类型的泛左值,因此这样的转换函数被认为在选择候选函数的过程中产生 X。
\n
因此,无论#1或#2,它们都被视为产生类型T。它们都有 隐式参数对象T&,因此 [over.match.best#2.1] 无法确定哪个是最好的
\n\n对于某些参数 j,ICSj(F1) 是比 ICSj(F2) 更好的转换序列,或者,如果不是这样,
\n
能够确定哪种过载最好的唯一希望落在 [over.match.best#2.2] 上
\n\n\n上下文是通过用户定义的转换进行的初始化(请参阅 [dcl.init]、[over.match.conv] 和 [over.match.ref])以及从 F1 的返回类型到目标类型的标准转换序列(即正在初始化的实体的类型)是比从 F2 的返回类型到目标类型的标准转换序列更好的转换序列
\n
它们的标准转换序列都是身份转换。因此,它们应该是含糊的。但GCC和Clang有各自的解释,并不一致。我想知道哪种解释是正确的?
\n| 归档时间: |
|
| 查看次数: |
127 次 |
| 最近记录: |