考慮以下代碼:爲什麼這個引用綁定不合格?
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