考虑以下代码:为什么这个引用绑定不合格?
int **p = 0;
class S {
public:
explicit operator int**&() {
return p;
}
};
int main() {
S a;
int *const*&b (a); // error in both g++-7 and clang-5.0 with "-std=c++17"
return 0;
}
你们会同意
- 从
int**
资格转换为int*const*
是可能的, int *const*&b (a)
是直接初始化。
首先,我们参考来自n4700的11.6.3段落[dcl.init.ref]。
的参考输入“CV1
T1 (= int*const*)
”是由一种类型的表达式初始化“CV2T2 (= S)
”如下:
- 如果参考是一个左值参考和初始化表达式
- ...
- 具有类类型(即,
T2
是一个类型),其中T1
不引用相关于T2
,并且可以被转换成类型的左值“CV3T3
”,其中“CV1T1
”是参考兼容“CV3T3
”(这种转换通过枚举适用转换函数(16.3.1.6)和通过重载解析(16.3)选择最好的一个所选择的),然后的引用绑定到在第一种情况下的初始化表达式左值和到在第二种情况下转换的左值结果...
这里,我们预计T3
是int*const*
。如上所述,是否可能转换是根据16.3.1.6第1段[over.match.ref]确定的。
...假设“参照CV1
T
”是基准是 初始化的类型,和“CVS
”是初始值设定表达式的类型,与S
类类型,候选功能选择如下:
- ...对于直接初始化,那些显式转换函数该 没有内
S
和产量类型隐藏的“左值参考CV2T2
”或“CV2T2
”或“右值参照CV2T2
”,分别其中T2
与T
相同,或者可以转换为T
类型,并且资格转换也是候选功能。
这里,S::operator int**&
产量“左值参照T2 (= int**)
”,它可以通过一个资格转换被转换为T (= int*const*)
。在这里,我们可以说转换是可能的,但是程序在g ++ - 7和clang-5.0中都不被接受。这是为什么?
完全出于同样的原因,为什么'int&a = 1;'无法编译,但我不知道足够引用任何特定段落的标准。 – Rakete1111
@ Rakete1111这是为什么?在我的情况下,转换产生一个左值。 – b1sub
但是,左值的类型是'int **',但是你需要'int * const *',所以发生了转换。 – Rakete1111