通过模糊转换运算符引用绑定

use*_*538 8 c++ visual-studio copy-initialization c++11 c++14

#include <iostream>
using namespace std;

struct CL2
{
    CL2(){}
    CL2(const CL2&){}
};

CL2 cl2;

struct CL1
{
    CL1(){}
    operator CL2&(){cout<<"operator CL2&"; return cl2;}
    operator const CL2&(){cout<<"operator const CL2&"; return cl2;}
};

CL1 cl1;

int main()
{
    CL1 cl1;
    CL2 cl2 (cl1);
}
Run Code Online (Sandbox Code Playgroud)

clang和gcc都提供了不明确的转换运算符,但Visual Studio编译好并打印"operator const CL2&".按标准怎么做才对?
正如我所说,将CL1转换为const CL2&是在复制初始化上下文中(作为cl2对象的直接初始化的一部分).我看过n4296草案,[over.match.copy]:

假设"cv1 T"是要初始化的对象的类型,使用T类类型,候选函数选择如下:
- T的转换构造函数(12.3.1)是候选函数.
- 当初始化表达式的类型是类类型"cv S"时,将考虑S及其基类的非显式转换函数.初始化临时绑定到构造函数的第一个参数时,其中参数的类型为"引用可能的cv-qualified T",并且在直接初始化类型的对象的上下文中使用单个参数调用构造函数"cv2 T",也考虑了显式转换函数.那些未隐藏在S中并且产生其cv非限定版本与T的类型相同或者是其派生类的类型的候选函数.返回"引用X"的转换函数返回lvalues或xvalues,具体取决于类型X的引用类型,因此被认为是为此选择候选函数的过程产生X.

即两个转换运算符被认为是返回CL2和const CL2(不仅仅是没有const的CL2)并且它仍然需要解决,哪个转换更好:CL2 - > const CL2&或const CL2 - > const CL2&.第二种情况似乎更合适.在这种情况下是否应考虑更好的资格转换?或两种情况都是身份转换?我在标准版中找不到它

Col*_*mbo 5

由于两个转换运算符具有相同的签名,因此优先选择其中一个的唯一方法是应用 [over.match.best]/(1.4)\xe2\x80\xa6

\n\n
\n

\xe2\x80\x94 上下文是通过用户定义的转换(参见 8.5、\n 13.3.1.5 和 13.3.1.6)以及从返回类型F1到目标类型(即类型正在初始化的实体的\n )是比从返回类型F2到目标类型的\n 标准转换序列更好的转换序列。

\n
\n\n

\xe2\x80\xa6 或 (1.5):

\n\n
\n

\xe2\x80\x94 上下文是通过转换函数进行初始化,用于对函数类型的引用的直接\n 引用绑定 (13.3.1.6),[\xe2\x80\xa6]

\n
\n\n

显然,两者都不适用,因此存在歧义。消除歧义的可能方法:

\n\n
operator CL2&();\noperator const CL2&() const; \n
Run Code Online (Sandbox Code Playgroud)\n\n

演示;在这里,前一个重载的隐式对象参数的初始标准转换序列根据 [over.ics.rank]/(3.2.6) 更好,这由 [over.match.best]/(1.3) 决定。

\n