c++ - 通过不明确的转换运算符进行引用绑定(bind)

标签 c++ visual-studio c++11 c++14 copy-initialization

#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 编译正常并打印“operator const CL2&”。怎样才符合标准?
据我所知,将 CL1 转换为 const CL2& 是在复制初始化上下文中(作为 cl2 对象直接初始化的一部分)。我看过n4296草稿,[over.match.copy]:

Assuming that “cv1 T” is the type of the object being initialized, with T a class type, the candidate functions are selected as follows:
— The converting constructors (12.3.1) of T are candidate functions.
— When the type of the initializer expression is a class type “cv S”, the non-explicit conversion functions of S and its base classes are considered. When initializing a temporary to be bound to the first parameter of a constructor where the parameter is of type “reference to possibly cv-qualified T” and the constructor is called with a single argument in the context of direct-initialization of an object of type “cv2 T”, explicit conversion functions are also considered. Those that are not hidden within S and yield a type whose cv-unqualified version is the same type as T or is a derived class thereof are candidate functions. Conversion functions that return “reference to X” return lvalues or xvalues, depending on the type of reference, of type X and are therefore considered to yield X for this process of selecting candidate functions.

即这两个转换运算符都被视为 return CL2 和 const CL2(不仅仅是没有 const 的 CL2),还有待解决,哪个转换更好:CL2 -> const CL2& 或 const CL2 -> const CL2&。第二种情况似乎更合适。在这种情况下是否应该考虑更好的资格转换?或者两种情况都是身份转换?我在标准版中找不到它

最佳答案

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

— the context is an initialization by user-defined conversion (see 8.5, 13.3.1.5, and 13.3.1.6) and the standard conversion sequence from the return type of F1 to the destination type (i.e., the type of the entity being initialized) is a better conversion sequence than the standard conversion sequence from the return type of F2 to the destination type.

…或(1.5):

— the context is an initialization by conversion function for direct reference binding (13.3.1.6) of a reference to function type, […]

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

operator CL2&();
operator const CL2&() const; 

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

关于c++ - 通过不明确的转换运算符进行引用绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34119876/

相关文章:

c++ - 如何在使用 SDL2 的 Eclipse 中构建 C++ 程序

javascript - Visual Studio、ASP.Net (.Net Framework) 以及在项目中包含 NuGet 安装的包

visual-studio - Silverlight打印中 "Dialogs must be user-initiated"安全异常的另一个技巧

c++ - 分布在 -DBL_MAX 和 DBL_MAX 之间的随机 double

c++ - 类型删除工作或失败取决于优化级别

如果值来自成员变量,则C++复制初始化和const引用初始化之间的区别

c++ - 模板重载的行为不同于非模板重载

c++ - 为什么while循环的执行时间显得如此奇怪?

c++ - 获取数字最左边两位的值的最便宜方法是什么?

matlab - mex 文件编译没有错误但不能在 matlab 中工作