名稱空間
變體
操作

隱式轉換

來自 cppreference.com
< cpp‎ | 語言
 
 
C++ 語言
 
 

當型別 T1 的表示式被用在不接受該型別但接受其他型別 T2 的語境中時,就會執行隱式轉換;特別是在以下情況:

  • 當表示式作為引數用於呼叫宣告引數型別為 T2 的函式時;
  • 當表示式作為期望 T2 的運算子的運算元時;
  • 當初始化一個型別為 T2 的新物件時,包括函式返回 T2 時使用的 return 語句;
  • 當表示式用於 switch 語句時(T2 為整型);
  • 當表示式用於 if 語句或迴圈時(T2bool)。

只有當存在一個從 T1T2 的明確的*隱式轉換序列*時,程式才格式良好(可編譯)。

如果被呼叫的函式或運算子有多個過載,在構建了從 T1 到每個可用 T2 的隱式轉換序列後,過載決議規則將決定哪個過載被編譯。

注意:在算術表示式中,二元運算子運算元的隱式轉換的目標型別由一套獨立的規則決定:常用算術轉換

目錄

[編輯] 轉換順序

隱式轉換序列按以下順序包含:

1) 零個或一個*標準轉換序列*;
2) 零個或一個*使用者定義轉換*;
3) 零個或一個*標準轉換序列*(僅當使用了使用者定義轉換時)。

在考慮建構函式或使用者定義轉換函式的引數時,只允許一個標準轉換序列(否則使用者定義轉換可能被有效地連結)。當從一個非類型別轉換為另一個非類型別時,只允許一個標準轉換序列。

標準轉換序列按以下順序包含:

1) 零個或一個來自以下集合的轉換:
  • 左值到右值轉換,
  • *陣列到指標轉換*,以及
  • 函式到指標轉換;
2) 零個或一個*數值提升*或*數值轉換*;
3) 零個或一個*函式指標轉換*;
(C++17 起)
4) 零個或一個*限定符轉換*。

使用者定義轉換包含零個或一個非顯式單引數轉換建構函式或非顯式轉換函式呼叫。

當且僅當 T2 可以從 e 複製初始化時,表示式 e 被認為是*隱式可轉換為 T2*,即對於某個虛構的臨時變數 t,宣告 T2 t = e; 是格式良好的(可以編譯)。請注意,這與直接初始化T2 t(e))不同,直接初始化還會考慮顯式建構函式和轉換函式。

[編輯] 上下文轉換

在以下語境中,期望型別 bool,如果宣告 bool t(e); 格式良好(即,考慮了顯式轉換函式,例如 explicit T::operator bool() const;),則執行隱式轉換。這樣的表示式 e 被稱為*上下文轉換為 bool*。

  • ifwhilefor 的控制表示式;
  • 內建邏輯運算子 !&&|| 的運算元;
  • 條件運算子 ?: 的第一個運算元;
  • static_assert 宣告中的謂詞;
  • noexcept 說明符中的表示式;
(C++20 起)
(C++11 起)

在以下語境中,期望上下文特定型別 T,並且類型別 E 的表示式 e 僅在以下情況允許:

(C++14 前)
  • 在允許型別中,正好存在一個型別 T,使得 E 具有非顯式轉換函式,其返回型別為(可能帶有 cv 限定符的)T 或對(可能帶有 cv 限定符的)T 的引用,並且
  • e 可以隱式轉換為 T
(C++14 起)

這樣的表示式 e 被稱為*上下文隱式轉換為*指定的型別 T請注意,顯式轉換函式不被考慮,即使它們在上下文轉換為 bool 時被考慮。(C++11 起)

  • delete-expression 的引數(T 是任何物件指標型別);
  • 整型常量表達式,其中使用了字面量類(T 是任何整型或無作用域列舉型別,所選的使用者定義轉換函式必須是 constexpr);
  • switch 語句的控制表示式(T 是任何整型或列舉型別)。
#include <cassert>
 
template<typename T>
class zero_init
{
    T val;
public:
    zero_init() : val(static_cast<T>(0)) {}
    zero_init(T val) : val(val) {}
    operator T&() { return val; }
    operator T() const { return val; }
};
 
int main()
{
    zero_init<int> i;
    assert(i == 0);
 
    i = 7;
    assert(i == 7);
 
    switch (i) {}     // error until C++14 (more than one conversion function)
                      // OK since C++14 (both functions convert to the same type int)
    switch (i + 0) {} // always okay (implicit conversion)
}

[編輯] 值轉換

值轉換是改變表示式值類別的轉換。當表示式作為運算子的操作數出現,而運算子期望不同值類別的表示式時,就會發生值轉換。

  • 每當 glvalue 作為需要 prvalue 的運算子的操作數出現時,會應用*左值到右值*、*陣列到指標*或*函式到指標*的標準轉換,將表示式轉換為 prvalue。
  • 除非另有說明,每當 prvalue 作為期望 glvalue 的運算子的操作數出現時,會應用*臨時物件實質化轉換*,將表示式轉換為 xvalue。
(C++17 起)

[編輯] 左值到右值轉換

任何非函式、非陣列型別 T左值(C++11 前)任何非函式、非陣列型別 Tglvalue(C++11 起) 可以隱式轉換為右值(C++11 前)prvalue(C++11 起)

  • 如果 T 不是類型別,則右值(C++11 前)prvalue(C++11 起) 的型別是 T 的 cv 非限定版本。
  • 否則,右值(C++11 前)prvalue(C++11 起) 的型別是 T

如果程式需要從不完全型別進行左值到右值轉換,則該程式格式錯誤。

給定 左值(C++11 前)glvalue(C++11 起) 所指的物件為 obj

  • sizeof 運算元的內部發生左值到右值轉換時,obj 中包含的值不會被訪問,因為該運算子不評估其運算元。
  • 轉換結果是 obj 中包含的值。如果 Tobj 的型別之一是有符號整型,另一個是相應的無符號整型,則結果是型別為 T 的值,其值表示與 obj 相同。
(C++11 前)
  • 當對錶達式 E 應用左值到右值轉換時,如果滿足以下條件,則不訪問 obj 中包含的值:
  • 轉換結果確定如下:
  • 如果 T 是(可能帶有 cv 限定符的)std::nullptr_t,則結果是空指標常量obj 不會被轉換訪問,因此即使 T 是 volatile 限定的,也沒有副作用,並且 glvalue 可以引用 union 的非活動成員。
  • 否則,如果 T 是類型別
(C++17 前)
(C++17 起)
  • 否則,如果 obj 包含無效指標值,則行為是實現定義的。
  • 否則,如果 obj值表示中的位對於 obj 的型別無效,則行為是未定義的。
  • 否則,讀取 obj,並且(C++20 起) 結果是 obj 中包含的值。如果 Tobj 的型別之一是有符號整型,另一個是相應的無符號整型,則結果是型別為 T 的值,其值表示與 obj 相同。
(C++11 起)

此轉換模擬將值從記憶體位置讀取到 CPU 暫存器的行為。

[編輯] 陣列到指標轉換

NT 陣列”或“未知邊界的 T 陣列”型別的左值右值可以隱式轉換為“指向 T 的指標”型別的prvalue如果陣列是 prvalue,則會發生臨時物件實質化(C++17 起) 結果指標指向陣列的第一個元素(詳情請參閱陣列到指標退化)。

[編輯] 函式到指標轉換

函式型別的左值可以隱式轉換為prvalue指向該函式的指標。這不適用於非靜態成員函式,因為不存在引用非靜態成員函式的左值。

臨時物件實質化

任何完整型別 Tprvalue 可以轉換為相同型別 T 的 xvalue。此轉換透過將 prvalue 評估為臨時物件的結果物件,從而從 prvalue 初始化型別 T 的臨時物件,並生成表示該臨時物件的 xvalue。

如果 T 是類型別或類型別的陣列,它必須有一個可訪問且未刪除的解構函式。

struct S { int m; };
int i = S().m; // member access expects glvalue as of C++17;
               // S() prvalue is converted to xvalue

臨時物件實質化發生在以下情況:

請注意,當從相同型別的 prvalue 初始化物件時(透過直接初始化複製初始化),不會發生臨時物件實質化:這樣的物件直接從初始化器初始化。這確保了“保證的複製省略”。

(C++17 起)

[編輯] 整型提升

小型整型(例如 char)和無作用域列舉型別的prvalue 可以轉換為較大整型(例如 int)的 prvalue。特別是,算術運算子不接受小於 int 的型別作為引數,如果適用,在左值到右值轉換後會自動應用整型提升。此轉換始終保留值。

本節中的以下隱式轉換被歸類為*整型提升*。

請注意,對於給定源型別,整型提升的目標型別是唯一的,所有其他轉換都不是提升。例如,過載決議會選擇 char -> int(提升)而非 char -> short(轉換)。

[編輯] 從整型提升

型別 bool 的 prvalue 可以轉換為型別 int 的 prvalue,其中 false 變為 0true 變為 1

對於除 bool 外的整型 T 的 prvalue val

1) 如果 val 是應用於位域的左值到右值轉換的結果,
  • 如果 int 可以表示位域的所有值,則 val 可以轉換為型別 int 的 prvalue;
  • 否則,如果 unsigned int 可以表示位域的所有值,則 val 可以轉換為 unsigned int
  • 否則,val 可以根據專案 (3) 中指定的規則進行轉換。
2) 否則(val 不是從位域轉換而來),
  • 如果 Tchar8_t, (C++20 起)char16_t, char32_t(C++11 起)wchar_t,則 val 可以根據專案 (3) 中指定的規則進行轉換;
  • 否則,如果 T整數轉換等級低於 int 的等級
  • 如果 int 可以表示 T 的所有值,則 val 可以轉換為型別 int 的 prvalue;
  • 否則,val 可以轉換為型別 unsigned int 的 prvalue。
3) 在專案 (1)(轉換後的位域不適合 unsigned int)或專案 (2)(T 是給定字元型別之一)指定的案例中,val 可以轉換為以下型別中第一個可以表示其底層型別所有值的 prvalue
  • int
  • unsigned int
  • long
  • unsigned long
  • long long
  • unsigned long long
  • T 的底層型別
(C++11 起)

[編輯] 從列舉型別提升

底層型別不固定的無作用域列舉型別的 prvalue 可以轉換為以下列表中第一個能夠容納其整個值範圍的型別的 prvalue

  • int
  • unsigned int
  • long
  • unsigned long
  • 整數轉換等級高於 long long 的等級,
  • 其整數轉換等級在所有擴充套件整型中最低,並且
  • 如果存在兩個在所有擴充套件整型中整數轉換等級最低的型別,則它是有符號的。
(C++11 起)


底層型別固定的無作用域列舉型別的 prvalue 可以轉換為其底層型別。此外,如果底層型別也受整型提升影響,則轉換為提升後的底層型別。為了過載決議的目的,轉換為未提升的底層型別更好。

(C++11 起)

[編輯] 浮點型提升

型別 floatprvalue 可以轉換為型別 double 的 prvalue。值不會改變。

此轉換稱為*浮點型提升*。

[編輯] 數值轉換

與提升不同,數值轉換可能會改變值,並可能導致精度損失。

[編輯] 整型轉換

整型或無作用域列舉型別的prvalue 可以轉換為任何其他整型。如果轉換列在整型提升下,則它是一種提升而不是轉換。

  • 如果目標型別是無符號的,則結果值是等於源值 2n
    的最小無符號值,其中 n 是用於表示目標型別的位數。
  • 也就是說,根據目標型別是更寬還是更窄,有符號整數分別進行符號擴充套件[1]或截斷,無符號整數分別進行零擴充套件或截斷。
  • 如果目標型別是有符號的,並且源整數可以在目標型別中表示,則值不會改變。否則,結果是實現定義的(C++20 前)目標型別中唯一的值,該值等於源值模 2n
    ,其中 n 是用於表示目標型別的位數
    (C++20 起)
    (請注意,這與有符號整數算術溢位不同,後者是未定義的)。
  • 如果源型別是 bool,則值 false 轉換為零,值 true 轉換為目標型別的值一(請注意,如果目標型別是 int,這是一種整型提升,而不是整型轉換)。
  • 如果目標型別是 bool,這是一種布林轉換(見下文)。
  1. 這僅適用於補碼算術,僅精確寬度整數型別要求使用補碼。但請注意,目前所有具有 C++ 編譯器的平臺都使用補碼算術。

[編輯] 浮點型轉換

浮點型別的prvalue 可以轉換為任何其他浮點型別的 prvalue。

(直至 C++23)

浮點型別的prvalue 可以轉換為任何其他浮點型別的 prvalue,且該目標浮點型別的浮點轉換等級大於或等於源型別。

標準浮點型別的prvalue 可以轉換為任何其他標準浮點型別的 prvalue。

static_cast 可以用於將浮點型別的 prvalue 顯式轉換為任何其他浮點型別。

(C++23 起)

如果轉換列在浮點提升下,則它是一種提升而不是轉換。

  • 如果源值可以在目標型別中精確表示,則它不會改變。
  • 如果源值介於目標型別的兩個可表示值之間,則結果是這兩個值之一(具體是哪一個由實現定義,儘管如果支援 IEEE 算術,則預設四捨五入到最近)。
  • 否則,行為未定義。

[編輯] 浮點-整型轉換

浮點型別的prvalue 可以轉換為任何整型型別的 prvalue。小數部分被截斷,即小數部分被丟棄。

  • 如果截斷後的值不能適合目標型別,則行為是未定義的(即使目標型別是無符號的,模算術也不適用)。
  • 如果目標型別是 bool,這是一種布林轉換(見下文)。

整型或無作用域列舉型別的 prvalue 可以轉換為任何浮點型別的 prvalue。如果可能,結果是精確的。

  • 如果值可以適合目標型別但不能精確表示,則選擇最接近的更高或更低的可表示值是實現定義的,儘管如果支援 IEEE 算術,則預設四捨五入到最近
  • 如果值不能適合目標型別,則行為是未定義的。
  • 如果源型別是 bool,則值 false 轉換為零,值 true 轉換為一。

[編輯] 指標轉換

空指標常量可以轉換為任何指標型別,結果是該型別的空指標值。這種轉換(稱為*空指標轉換*)允許作為單次轉換轉換為 cv 限定型別,即它不被視為數值轉換和限定符轉換的組合。

指向任何(可選 cv 限定的)物件型別 Tprvalue 指標可以轉換為指向(相同 cv 限定的)void 的 prvalue 指標。結果指標表示與原始指標值相同的記憶體位置。

  • 如果原始指標是空指標值,則結果是目標型別的空指標值。

型別為“指向(可能帶有 cv 限定符的)Derived 的指標”的 prvalue ptr 可以轉換為型別為“指向(可能帶有 cv 限定符的)Base 的指標”的 prvalue,其中 BaseDerived基類,且 Derived 是一個完全的類型別。如果 Base 不可訪問或不明確,則程式格式錯誤。

  • 如果 ptr 是空指標值,則結果也是空指標值。
  • 否則,如果 BaseDerived虛基類,並且 ptr 不指向型別與 Derived 相似且在其生命週期內或其構造或析構期間的物件,則行為是未定義的。
  • 否則,結果是指向派生類物件中基類子物件的指標。

[編輯] 成員指標轉換

空指標常量可以轉換為任何成員指標型別,結果是該型別的空成員指標值。這種轉換(稱為*空成員指標轉換*)允許作為單次轉換轉換為 cv 限定型別,即它不被視為數值轉換和限定符轉換的組合。

型別為“指向 Base 中型別為(可能帶有 cv 限定符的)T 的成員的指標”的prvalue 可以轉換為型別為“指向 Derived 中型別為(相同 cv 限定的)T 的成員的指標”的 prvalue,其中 BaseDerived 的基類,且 Derived 是一個完整的類型別。如果 Base 不可訪問、不明確、是 Derived 的虛基類或 Derived 的某個中間虛基類的基類,則程式格式錯誤。

  • 如果 Derived 不包含原始成員,也不是包含原始成員的類的基類,則行為是未定義的。
  • 否則,結果指標可以用 Derived 物件解引用,它將訪問該 Derived 物件中 Base 基子物件內的成員。

[編輯] 布林轉換

整型、浮點型、無作用域列舉、指標和成員指標型別的prvalue 可以轉換為型別 bool 的 prvalue。

零值(對於整型、浮點型和無作用域列舉)以及空指標和空成員指標值變為 false。所有其他值變為 true

直接初始化的語境中,bool 物件可以從型別 std::nullptr_t 的 prvalue 初始化,包括 nullptr。結果值為 false。然而,這不被認為是隱式轉換。

(C++11 起)

[編輯] 限定符轉換

一般來說:

  • 指向cv 限定型別 T 的指標的prvalue 可以轉換為指向更 cv 限定的相同型別 T 的 prvalue(換句話說,可以新增 constness 和 volatility)。
  • 指向類 X 中 cv 限定型別 T 的成員的指標的 prvalue 可以轉換為指向類 X更 cv 限定型別 T 的成員的指標的 prvalue。

“限定符轉換”的正式定義見下文

[編輯] 相似型別

非正式地說,如果忽略頂層 cv-限定符,兩種型別是*相似*的:

  • 它們是相同的型別;或者
  • 它們都是指標,並且指向的型別是相似的;或者
  • 它們都是指向同一類的成員的指標,並且指向的成員型別是相似的;或者
  • 它們都是陣列,並且陣列元素型別是相似的。

例如:

  • const int* const *int** 是相似的;
  • int (*)(int*)int (*)(const int*) 不相似;
  • const int (*)(int*)int (*)(int*) 不相似;
  • int (*)(int* const)int (*)(int*) 是相似的(它們是相同的型別);
  • std::pair<int, int>std::pair<const int, int> 不相似。

形式上,型別相似性是根據限定符分解來定義的。

型別 T 的*限定符分解*是一個由元件 cv_iP_i 組成的序列,使得 T 是“cv_0 P_0 cv_1 P_1 ... cv_n−1 P_n−1 cv_n U”,其中非負數 n,其中

  • 每個 cv_i 都是一組 constvolatile,並且
  • 每個 P_i
  • “指向”,
  • “指向類 C_i 的型別成員”,
  • N_i 陣列”,或
  • “未知邊界陣列”。

如果 P_i 表示一個數組,則元素型別上的 cv 限定符 cv_i+1 也被視為陣列的 cv 限定符 cv_i

// T is “pointer to pointer to const int”, it has 3 qualification-decompositions:
// n = 0 -> cv_0 is empty, U is “pointer to pointer to const int”
// n = 1 -> cv_0 is empty, P_0 is “pointer to”,
//          cv_1 is empty, U is “pointer to const int”
// n = 2 -> cv_0 is empty, P_0 is “pointer to”,
//          cv_1 is empty, P_1 is “pointer to”,
//          cv_2 is “const", U is “int”
using T = const int**;
 
// substitute any of the following type to U gives one of the decompositions:
// U = U0 -> the decomposition with n = 0: U0
// U = U1 -> the decomposition with n = 1: pointer to [U1]
// U = U2 -> the decomposition with n = 2: pointer to [pointer to [const U2]]
using U2 = int;
using U1 = const U2*;
using U0 = U1*;

如果 T1T2 都存在一個限定符分解,且這兩個限定符分解滿足以下所有條件,則它們是*相似*的:

  • 它們的 n 相同。
  • U 表示的型別相同。
  • 對應的 P_i 元件對於所有 i 都是相同的,或者一個元件是“大小為 N_i 的陣列”,另一個是“未知大小的陣列”(C++20 起)
// the qualification-decomposition with n = 2:
// pointer to [volatile pointer to [const int]]
using T1 = const int* volatile *;
 
// the qualification-decomposition with n = 2:
// const pointer to [pointer to [int]]
using T2 = int** const;
 
// For the two qualification-decompositions above
// although cv_0, cv_1 and cv_2 are all different,
// they have the same n, U, P_0 and P_1,
// therefore types T1 and T2 are similar.

[編輯] 組合 cv-限定符

在下文中,型別 Tn 的最長限定符分解表示為 Dn,其元件表示為 cvn_iPn_i

型別 T1 的 prvalue 表示式可以轉換為型別 T2,如果滿足以下所有條件:

  • T1T2 是相似的。
  • 對於每個非零 i,如果 const 存在於 cv1_i 中,則 const 也存在於 cv2_i 中,volatile 同理。
  • 對於每個非零 i,如果 cv1_icv2_i 不同,則 const 存在於 [1i) 中所有 kcv2_k 中。

兩種型別 T1T2 的*限定符組合型別*是與 T1 相似的型別 T3,使得

  • cv3_0 為空,
  • 對於每個非零 icv3_icv1_icv2_i 的並集,並且
  • 如果 cv3_icv1_ic2_i 不同,則 const 會新增到 [1i) 中所有 kcv3_k 中。
(C++20 前)

兩種型別 T1T2 的*限定符組合型別*是與 T1 相似的型別 T3,其中 D3 滿足以下所有條件:

  • cv3_0 為空。
  • 對於每個非零 icv3_icv1_icv2_i 的並集。
  • 如果 P1_iP2_i 是“未知邊界陣列”,則 P3_i 是“未知邊界陣列”,否則它是 P1_i
  • 如果 cv3_icv1_icv2_i 不同,或者 P3_iP1_iP2_i 不同,則 const 會新增到 [1i) 中所有 kcv3_k 中。

如果 T1T2 的限定符組合型別是 cv-非限定的 T2,則型別 T1 的 prvalue 可以轉換為型別 T2

(C++20 起)
// longest qualification-decomposition of T1 (n = 2):
// pointer to [pointer to [char]]
using T1 = char**;
 
// longest qualification-decomposition of T2 (n = 2):
// pointer to [pointer to [const char]]
using T2 = const char**;
 
// Determining the cv3_i and T_i components of D3 (n = 2):
// cv3_1 = empty (union of empty cv1_1 and empty cv2_1)
// cv3_2 = “const” (union of empty cv1_2 and “const” cv2_2)
// P3_0 = “pointer to” (no array of unknown bound, use P1_0)
// P3_1 = “pointer to” (no array of unknown bound, use P1_1)
// All components except cv_2 are the same, cv3_2 is different from cv1_2,
// therefore add “const” to cv3_k for each k in [1, 2): cv3_1 becomes “const”.
// T3 is “pointer to const pointer to const char”, i.e., const char* const *.
using T3 = /* the qualification-combined type of T1 and T2 */;
 
int main()
{
    const char c = 'c';
    char* pc;
    T1 ppc = &pc;
    T2 pcc = ppc; // Error: T3 is not the same as cv-unqualified T2,
                  //        no implicit conversion.
 
    *pcc = &c;
    *pc = 'C';    // If the erroneous assignment above is allowed,
                  // the const object “c” may be modified.
}

請注意,在 C 程式語言中,const/volatile 只能新增到第一級。

char** p = 0;
char * const* p1 = p;       // OK in C and C++
const char* const * p2 = p; // error in C, OK in C++

函式指標轉換

  • 指向非丟擲函式的prvalue 指標可以轉換為指向可能丟擲函式的 prvalue 指標。
  • 指向非丟擲成員函式的 prvalue 指標可以轉換為指向可能丟擲成員函式的 prvalue 指標。
void (*p)();
void (**pp)() noexcept = &p; // error: cannot convert to pointer to noexcept function
 
struct S
{
    typedef void (*p)();
    operator p();
};
void (*q)() noexcept = S(); // error: cannot convert to pointer to noexcept function
(C++17 起)

[編輯] 安全的布林問題

在 C++11 之前,設計一個在布林上下文(例如 if (obj) { ... })中可用的類存在問題:給定一個使用者定義的轉換函式,例如 T::operator bool() const;,隱式轉換序列允許在該函式呼叫之後再進行一個標準轉換序列,這意味著結果的 bool 可以轉換為 int,從而允許諸如 obj << 1;int i = obj; 的程式碼。

一個早期的解決方案可以在 std::basic_ios 中看到,它最初定義了 operator void*,這樣像 if (std::cin) {...} 這樣的程式碼可以編譯,因為 void* 可以轉換為 bool,但 int n = std::cout; 不會編譯,因為 void* 不能轉換為 int。這仍然允許諸如 delete std::cout; 這樣的無意義程式碼編譯。

許多 C++11 之前的第三方庫都設計了一個更精巧的解決方案,稱為 安全布林習語std::basic_ios 也透過 LWG issue 468 允許了這種習語,並且 operator void* 被替換(參見註釋)。

自 C++11 起,顯式 bool 轉換也可用於解決安全布林問題。

[編輯] 缺陷報告

下列更改行為的缺陷報告追溯地應用於以前出版的 C++ 標準。

缺陷報告 應用於 釋出時的行為 正確的行為
CWG 170 C++98 成員指標轉換的行為不明確
如果派生類沒有原始成員
已明確
CWG 172 C++98 列舉型別基於其底層型別進行提升 改為基於其值範圍
CWG 330
(N4261)
C++98 double* const (*p)[3]
double const * const (*p)[3] 的轉換是無效的
已修正為有效
CWG 519 C++98 空指標值不能保證在轉換到其他指標型別時
保留
始終保留
CWG 616 C++98 未初始化物件和無效值指標物件的左值到右值轉換行為
始終未定義
允許不確定 unsigned char
使用無效指標是實現定義的
是實現定義的
是實現定義的
CWG 685 C++98 列舉型別的底層型別在固定時未在整型提升中
優先
已優先
CWG 707 C++98 整型到浮點型轉換
在所有情況下都具有定義的行為
如果轉換的值超出目標範圍,則行為未定義
該值超出目標範圍
超出目標範圍
CWG 1423 C++11 std::nullptr_t 在直接初始化和複製初始化中都可以轉換為 bool
在直接初始化和複製初始化中
僅直接初始化
CWG 1773 C++11 在潛在評估表示式中出現的名稱表示式,如果命名的物件未被 ODR 使用,仍然可能在左值到右值轉換期間被評估
不評估
不評估
不評估
CWG 1781 C++11 std::nullptr_tbool 被認為是隱式轉換,即使它只對直接初始化有效
不再被視為隱式轉換
隱式轉換
隱式轉換
CWG 1787 C++98 從暫存器中快取的不確定 unsigned char 中讀取的行為是未定義的
讀取不確定 unsigned char 的行為是未定義的
已明確定義
CWG 1981 C++11 上下文轉換考慮顯式轉換函式 不考慮
CWG 2140 C++11 std::nullptr_t 左值進行的左值到右值轉換是否從記憶體中獲取這些左值,這一點不明確
std::nullptr_t 左值是否從記憶體中獲取這些左值,這一點不明確
不獲取
CWG 2310 C++98 對於派生到基的指標轉換和
基到派生的成員指標轉換,
派生類型別可以不完整
必須完整
CWG 2484 C++20 char8_tchar16_t 的整型提升策略不同,但它們都可以容納
它們
char8_t 應該以與 char16_t 相同的方式提升
char16_t 相同的方式
CWG 2485 C++98 涉及位域的整型提升未明確說明 改進了規範
CWG 2813 C++23 當呼叫類 prvalue 的顯式物件成員函式時,將發生臨時物件實質化
不會發生
不會發生
在這種情況下
CWG 2861 C++98 指向型別不可訪問物件的指標可以轉換為指向基類子物件的指標
轉換為指向基類子物件的指標
在這種情況下,行為是
未定義的
CWG 2879 C++17 臨時物件實質化轉換應用於作為期望 glvalue 的運算子運算元的 prvalue
在某些情況下不適用
在某些情況下不適用
CWG 2899 C++98 左值到右值轉換可以應用於具有無效值表示的左值
指示具有無效值表示的物件
在這種情況下,行為是
未定義的
CWG 2901 C++98 從引用值為 -1int 物件的 unsigned int 左值進行左值到右值轉換的結果不明確
引用值為 -1int 物件
已明確

[編輯] 另請參閱

C 文件 關於 隱式轉換