#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);
}
clang和gcc都给出了不明确的转换运算符,但Visual Studio编译好并打印&#34;运算符const CL2&amp;&#34;。根据标准必须如何正确?
在我看来,将CL1转换为const CL2&amp;在复制初始化上下文中(作为cl2对象的直接初始化的一部分)。我看过n4296草稿,[over.match.copy]:
假设“cv1 T”是要初始化的对象的类型, 使用T类类型,候选函数选择如下:
- T的转换构造函数(12.3.1)是候选者 功能。
- 初始化表达式的类型是a时 类类型“cv S”,S的非显式转换函数及其 考虑基类。初始化临时绑定时 到参数是类型的构造函数的第一个参数 “引用可能的cv-qualified T”并调用构造函数 在直接初始化的上下文中使用单个参数 对象类型为“cv2 T”,显式转换函数也是如此 考虑。那些没有隐藏在S中并产生一个类型的类型 cv-unqualified version与T的类型相同或是派生类 它是候选功能。 返回的转化功能 “引用X”返回左值或x值,具体取决于类型 因此,X的类型的引用被认为是为此产生X. 选择候选函数的过程。
即。两个转换运算符都被认为是返回CL2和const CL2(不仅仅是没有const的CL2)并且它仍然需要解决,哪个转换更好:CL2 - &gt; const CL2&amp;或const CL2 - &gt; const CL2&amp ;.第二种情况似乎更合适。在这种情况下是否应考虑更好的资格转换?或两种情况都是身份转换?我无法在标准
中找到它答案 0 :(得分:4)
由于两个转换运算符都具有相同的签名,因此唯一可以优先选择其中一个的方法是应用[over.match.best] /(1.4)......
- 上下文是用户定义转换的初始化(见8.5, 13.3.1.5和13.3.1.6)以及从
F1
的返回类型到目的地类型的标准转换序列(即,类型 正在初始化的实体)是比转换序列更好的转换序列 标准转换序列从返回类型F2
到。{ 目的地类型。
......或(1.5):
- 上下文是直接转换函数的初始化 引用绑定(13.3.1.6)对函数类型的引用,[...]
显然,两者都不适用,因此含糊不清。消除歧义的可能方法:
operator CL2&();
operator const CL2&() const;
Demo;这里,隐式对象参数的前一个重载的初始标准转换序列更好,因为[over.ics.rank] /(3.2.6),[over.match.best] /(1.3)是决定性的。