重载转换函数模板

Bar*_*rry 14 c++ conversion-operator language-lawyer overload-resolution

考虑以下:

struct X {
    template <class T> operator T();  // #1
    template <class T> operator T&(); // #2
};

int        a = X{}; // error: ambiguous
int&       b = X{}; // calls #2
int const& c = X{}; // calls #2
Run Code Online (Sandbox Code Playgroud)

这种情况b很简单,#2是唯一可行的候选人.表示初始化的#2首选规则是什么,但两者对于初始化是不明确的?#1int const&int

Col*_*mbo 3

当决定如何初始化给定初始值设定项的引用时,首先尝试直接绑定。[dcl.init.ref]/(5.1.2) :

\n\n
\n

如果引用是左值引用,并且初始化表达式 [\xe2\x80\xa6] 具有类类型(即,T2是类类型),其中T1与 不引用相关T2,并且可以\n 转换为类型 \xe2\x80\x9c cv3 T3 \xe2\x80\x9d,其中 \xe2\x80\x9c cv1 \xe2\x80\x9d 与 \xe2\x80\x9c cv3 \xe2\x80\x9dT1引用兼容(此转换通过枚举适用的转换函数 (13.3.1.6) 并通过重载决策 (13.3) 选择最佳函数来选择,然后将引用绑定 [\xe2\x80\xa6] 到转换的左值结果\n [\ xe2\x80\xa6]。 T3

\n
\n\n

管理此过程的候选选择的措辞(13.3.1.6,如上所述)排除了第一个转换函数:

\n\n
\n

S考虑了 及其基类的转换函数。那些未隐藏在其中S并产生类型 \xe2\x80\x9cl 对cv2 T2 \xe2\x80\x9d 的值引用的非显式转换函数\n (初始化对函数的左值引用或右值引用时)[\xe2\x80\ xa6],其中 \xe2\x80\x9c cv1 \xe2\x80\x9d 与 \xe2\x80\x9c cv2 \xe2\x80\x9dT是引用兼容的 (8.6.3)\n ,是候选函数。对于直接初始化,[\xe2\x80\xa6]。 T2

\n
\n\n

显然,这种排除是特定于引用初始化语义的,因此第一种情况仍然不明确。

\n