2017-12-27 145 views
5

考慮以下代碼:爲什麼這個引用綁定不合格?

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]。

的參考輸入「CV1T1 (= int*const*)」是由一種類型的表達式初始化「CV2T2 (= S)」如下:

  • 如果參考是一個左值參考和初始化表達式
    • ...
    • 具有類類型(即,T2是一個類型),其中T1不引用相關於T2,並且可以被轉換成類型的左值「CV3T3」,其中「CV1T1」是參考兼容「CV3T3」(這種轉換通過枚舉適用轉換函數(16.3.1.6)和通過重載解析(16.3)選擇最好的一個所選擇的),

然後的引用綁定到在第一種情況下的初始化表達式左值和到在第二種情況下轉換的左值結果...

這裏,我們預計T3int*const*如上所述,是否可能轉換是根據16.3.1.6第1段[over.match.ref]確定的。

...假設「參照CV1T」是基準是 初始化的類型,和「CVS」是初始值設定表達式的類型,與S類類型,候選功能選擇如下:

  • ...對於直接初始化,那些顯式轉換函數該 沒有內S和產量類型隱藏的「左值參考CV2T2」或「CV2T2」或「右值參照CV2T2」,分別其中T2T相同,或者可以轉換爲T類型,並且資格轉換也是候選功能

這裏,S::operator int**&產量「左值參照T2 (= int**)」,它可以通過一個資格轉換被轉換爲T (= int*const*)在這裏,我們可以說轉換是可能的,但是程序在g ++ - 7和clang-5.0中都不被接受。這是爲什麼?

+1

完全出於同樣的原因,爲什麼'int&a = 1;'無法編譯,但我不知道足夠引用任何特定段落的標準。 – Rakete1111

+0

@ Rakete1111這是爲什麼?在我的情況下,轉換產生一個左值。 – b1sub

+0

但是,左值的類型是'int **',但是你需要'int * const *',所以發生了轉換。 – Rakete1111

回答

7

我們正在尋找的參考初始化規則是[dcl.init.ref]

的參考輸入「CV1T1」是由一種類型的表達式「CV2T2」初始化如下:

我們有cv1T1 as int* const* and cv2T2 as S。然後,我們經過仔細下一節:

如果引用是一個左值引用和初始化表達式

  • 是一個左值(但不是位域),以及「CV1 T1」是參考兼容「CV2 T2」,或
  • 具有類類型(即,T2是一個類型),其中,T1是不能引用相關於T2,並且可以被轉換爲左值類型的「 cv3 T3「,其中」cv1 T1「與」cv3 T3「參考兼容(this轉換是通過枚舉適用轉換功能中選擇([over.match.ref])和選擇最佳的一個通過載分辨率),

那麼參考結合到初始化表達式左值在第一種情況下,並在第二種情況下(或者在任何情況下)轉換爲對象的適當基類子對象的左值結果。

我們的參考是一個左值參考。初始化表達式是一個左值,但這兩種類型不是reference-compatible,所以第一個項目符號不適用。

初始值設定項表達式具有非參考相關的類類型,但不能轉換爲參考兼容類型。參考兼容部分很重要。 int**不是參考兼容int* const*,而前者可以轉換爲後者,結果不會是一個左值 - 這也是必需的。

所以,本節不適用,我們move on

否則,引用應該是對非易失性常量類型的左值引用(即cv1應該是const),或者引用應該是右值引用。

我們的參考資料不符合這些標準,因此初始化不合格。


這種失敗的一個簡化版本是:

int* pi; 
int const*& r = pi; // error 

我們無法通過資格轉換去的時候,我們有一個左參考非const類型。

+0

我認爲**此用戶定義的轉換序列**的第二個標準轉換序列僅包含限定轉換,因此左值依然存在。爲什麼這是不可能的? – b1sub

+1

@ b1sub這些類型的問題對提問者的滿意度總是基本無法回答。直接的答案是資格轉換是根據[轉換價值](http://eel.is/c++draft/conv#qual-3)來定義的。 – Barry

+0

您的評論足夠了。我已經忽略了你提到的「prvalue」部分。 – b1sub