簡體   English   中英

prvalues的cv-qualifications (revisited)

[英]Cv-qualifications of prvalues (revisited)

這是我之前的問題的后續問題,其中明顯的共識是,prvalues 的 cv-qualifications 處理的變化只是一個相當小的和無關緊要的變化,旨在解決一些不一致的問題(例如,返回 prvalues 並聲明為 cv-qualified return 的函數類型)。

但是,我在標准中看到另一個地方似乎依賴於具有 cv 限定類型的純右值:通過臨時實現轉換使用純右值初始化const引用。 相關措辭可在9.3.3/5的多個位置找到

[...] 如果轉換后的初始值設定項是純右值,則其類型 T4 調整為類型“cv1 T4” ([conv.qual]) 並應用臨時實現轉換 ([conv.rval]) [...]

[...] 否則,初始化表達式被隱式轉換為“cv1 T1”類型的純右值。 應用臨時實現轉換並將引用綁定到結果。

目的顯然是為了確保當我們進行實際的臨時物化轉換

7.3.4 臨時實現轉換
1 T 類型的純右值可以轉換為 T 類型的 xvalue。此轉換通過使用臨時 object 作為其結果 ZA8CFDE63311C49EB66 評估純右值,從純右值初始化 T 類型的臨時 object ([class.temporary]) 並產生一個表示臨時 object 的 xvalue。 [...]

它作為輸入接收的類型T包括所需的 cv 限定。

但是,在非類非數組純右值的情況下,該 cv-qualification 如何在7.2.2/2中存活下來?

7.2.2 類型
2如果純右值最初具有類型“cv T”,其中 T 是無 cv 限定的非類、非數組類型,則表達式的類型在任何進一步分析之前調整為 T。

或者是嗎?

例如,在這個例子中我們得到什么樣的臨時

const int &r = 42;

是否是臨時const 我們能做到嗎

const_cast<int &>(r) = 101; // Undefined or not?

不觸發未定義的行為? 如果我沒記錯的話,最初的意圖是在這種情況下臨時獲得一個const int 還是真的嗎? (對於 class 類型,答案很明確 - 我們得到一個const臨時變量。)

對於

const int& r1=42

引用的類型為const int ,因此cv1const ,而prvalue的類型為const int ,因此物化臨時類型也為const int

例如,在這個例子中我們得到什么樣的臨時const int &r = 42; 是否是臨時常量?

讓我們分析您的示例,看看它是否為 const 。 鑒於這個例子

const int& r = 42;

標准的適用措辭是[dcl.init.ref]/5

對“ cv1 T1 ”類型的引用由“ cv2 T2 ”類型的表達式初始化,如下所示:

  • (5.1) [..]
  • (5.2) [..]
  • (5.3)否則,如果初始化表達式
    • (5.3.1)是右值(但不是位域)或 function 左值,“ cv1 T1 ”與“ cv2 T2 ”引用兼容,或
    • (5.3.2) [..]

那么第一種情況下的初始化表達式 的值 和第二種情況下的轉換結果稱為轉換后的初始化程序。 如果轉換后的初始值設定項是純右值,則將其類型 T4 調整為類型“cv1 T4” ([conv.qual]) 並應用臨時實現轉換 ([conv.rval])。 在任何情況下,引用都綁定到生成的 glvalue (或適當的基礎 class 子對象)。

已經知道初始化表達式42是純右值,並且const int ( cv1 T1 ) 與int ( cv2 T2 ) 是引用兼容的。 並且這里轉換的初始化程序是int ( T4 ) 類型; 然后通過[conv.qual]將其調整為const int ( cv1 T4 ); 然后應用臨時實現( [conv.rval] )。 但在應用它之前, [expr.type]/2開始:

如果prvalue最初具有類型“ cv T ”,其中T是無cv限定的非類、非數組類型,則表達式的類型在任何進一步分析之前調整為T

這里的進一步分析包括臨時實現轉換。

所以調整后的純右值的類型是int而不是const int 此時可以輸入[conv.rval]

T T的 xvalue。 此轉換初始化 T 類型的臨時 object ([class.temporary]) [..]

所以你有一個 xvalue 表示一個臨時類型的int 並且引用r綁定到生成的 glvalue (即, r綁定到表示臨時類型int而不是const int的 xvalue)。

據我所知,已創建的臨時不是const-qualified

你為什么懷疑7.2.2的語言? 在非類、非數組純右值上丟棄 cv 限定符似乎非常明確,因此臨時物化中的類型 T 是非常量、非易失性類型。

如果不是這種情況,那么您將無法將純右值綁定到非常量右值引用。 然而,該標准似乎極有可能接受這樣的程序:

#include <type_traits>

template<typename T> void
f(T &&t)
{
  static_assert(std::is_same_v<decltype(t), int&&>);
  ++t;
}

int
main()
{
  f(5);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM