![](/img/trans.png)
[英]Why in conditional operator (?:), second and third operands must have the same type?
[英]Conditional operator with same underlying class type
該程序應輸出0還是1? 在我閱讀和理解C ++ 14標准中引用的段落時,它應該打印1,但是GCC和clang都打印0(因為推導的類型是A const
而不是A const&
):
#include <iostream>
struct A {};
int main()
{
A a;
A const& ra = std::move(a); // #1
std::cout << std::is_same<decltype(true ? ra : std::move(a)),
A const&>::value; // Prints 0
}
在這種情況下, ra
是一個A const
值, std::move(a)
是一個A
x值,兩個類類型。 根據關於條件運算符(強調我的)的標准,結果應該是A const
類型的lvalue
,因此decltype
結果必須是A const&
:
[expr.cond] / 3否則,如果第二個和第三個操作數具有不同的類型並且具有(可能是cv限定的)類類型 ,或者兩者都是相同值類別的glvalues且除了cv-qualification之外的相同類型,嘗試將每個操作數轉換為另一個操作數的類型。 確定T1類型的操作數表達式E1是否可以轉換為匹配類型T2的操作數表達式E2的過程定義如下:
- 如果E2是左值 :如果E1可以被隱式轉換(第4節)到類型“左值引用T2” ,則E1可以被轉換為匹配E2,受制於轉換中引用必須直接綁定的約束(8.5。 3)到左值 。
[...]
在這種情況下, E2是ra
,它是一個左值,另一個可以隱含地轉換為“左值參考T2” ,如第// #1
行所示。 “對T2的左值引用”被翻譯為A const&
,因此, std::move(a)
直接綁定到A const
類型的左值,並且在轉換后,兩個操作數具有相同的類型和值類別,因此:
[expr.cond] / 3如果第二個和第三個操作數是相同值類別的glvalues並且具有相同的類型,則結果是該類型和值類別[...]。
因此,運算符結果應該是左值,並且decltype
結果應該是引用,因此程序應該打印1。
問題是措辭笨拙。 你應該問一下表達式的類型和值類別是true ? ra : std::move(a)
true ? ra : std::move(a)
應該是。 這個問題的答案是A const
類型的prvalue。 這隨后意味着程序應該打印0,因為我認為每個編譯器都正確。
?:
的規則相當復雜。 在這種情況下,我們有兩個類類型的表達式,我們試圖看看是否可以基於有限的規則子集相互轉換。
嘗試轉換ra
→ std::move(a)
失敗。 我們首先嘗試使用目標類型是A&&
,它不能直接綁定到ra
。 然后我們嘗試(3.3.1)中的備份計划,因為這兩個表達式具有相同的基礎類類型,但我們的目標表達式至少不像源表達式那樣是cv限定的,所以這也失敗了。
嘗試轉換std::move(a)
→ ra
失敗(3.1)因為我們需要直接綁定到左值(我們可以將rvalue綁定到const值左側,但是這里我們需要綁定一個左值)。 但是,在(3.3.1)備份成功,因為現在的目標類型至少與CV-合格作為源。
因此,我們應用轉換並繼續,好像第二個操作數是類型A const
的左值,但第三個操作數現在是類型A const
的prvalue(而不是類型A
的xvalue)。
(4)失敗,因為它們的價值類別不同。
因此, 結果是一個prvalue 。 因為它們具有相同的類型, 所以結果是這種類型 : A const
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.