通过不明确的转换运算符进行引用绑定

Reference binding through ambiguous conversion operator

#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)决定。