命名空間
變體
動作

常數運算式

出自 cppreference.com
< cpp‎ | language
 
 
C++ 語言
一般主題
流程控制
條件執行陳述式
if
疊代陳述式 (迴圈)
for
範圍 for (C++11)
跳躍陳述式
函式
函式宣告
Lambda 函式運算式
inline 指定符
動態例外規範 (直到 C++17*)
noexcept 指定符 (C++11)
例外
命名空間
型別
指定符
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
儲存期指定符
初始化
 
 

定義一個可以在編譯時期求值的運算式

此類運算式可用作非型別模板參數、陣列大小,以及其他需要常數運算式的場景,例如:

int n = 1;
std::array<int, n> a1;  // Error: “n” is not a constant expression
const int cn = 2;
std::array<int, cn> a2; // OK: “cn” is a constant expression

目錄

[編輯] 定義

屬於下列任何常數運算式類別的運算式即為常數運算式

C++98 常數運算式分類

整數常數運算式 (C++98)

在下列位置,C++ 要求運算式必須求值為整數或列舉常數

滿足以下所有條件的運算式為整數常數運算式 

  • 它僅涉及以下實體
  • 算術型別的常值 (literals)
  • 列舉元
  • 滿足以下所有條件的變數或靜態資料成員
  • 具有 const 限定。
  • 不具有 volatile 限定。
  • 為整數或列舉型別。
  • 以常數運算式進行初始化。
  • 它不使用任何浮點數常值,除非它們被顯式轉換為整數或列舉型別。
  • 它不對非整數且非列舉型別套用任何轉換。
  • 除了在 sizeof 的運算元中,它不使用以下任何實體
  • function
  • 類別物件
  • pointer
  • reference
  • 賦值運算子
  • 遞增運算子
  • 遞減運算子
  • 函式呼叫運算子
  • 逗號運算子

其他常數運算式類別

其他運算式僅為了常數初始化之目的而被視為常數運算式。此類常數運算式必須是下列運算式之一

  • 求值為 空指標值 的運算式
  • 求值為空成員指標值的運算式
  • 算術常數運算式
  • 位址常數運算式
  • 參考常數運算式
  • 完整物件型別的位址常數運算式,加或減一個整數常數運算式
  • 成員指標常數運算式

算術常數運算式是滿足整數常數運算式要求的運算式,但有以下例外

  • 浮點數常值可以不經顯式轉換而使用。
  • 可以套用向浮點型別的轉換。

位址常數運算式是滿足以下所有條件的指標型別運算式

  • 顯式使用取位址運算子
  • 隱式使用指標型別的非型別模板參數
  • 使用陣列或函式型別的運算式
  • 該運算式不呼叫任何函式。
  • 該運算式使用顯式指標轉換(除 dynamic_cast 外)及以下運算子且不存取結果物件
  • 下標運算子
  • 間接存取運算子
  • 取位址運算子
  • 成員存取運算子
  • 若使用了下標運算子,其運算元之一必須是整數常數運算式。

參考常數運算式是滿足以下所有條件的參考型別運算式

  • 該參考代表一個具有靜態儲存期的物件、參考型別的非型別模板參數或函式。該參考不代表非 POD 類別型別的成員或基底類別。
  • 該運算式不呼叫任何函式。
  • 該運算式使用顯式參考轉換(除 dynamic_cast 外)及以下運算子且不存取結果物件
  • 下標運算子
  • 間接存取運算子
  • 取位址運算子
  • 成員存取運算子
  • 若使用了下標運算子,其運算元之一必須是整數常數運算式。

成員指標常數運算式是一個成員指標型別的運算式,其中指標是藉由對限定識別字套用取位址運算子而建立,前綴可選擇性包含顯式的成員指標轉換。

(直到 C++11)

下列運算式統稱為常數運算式 

  • 具有靜態儲存期物件的位址
  • 函式的位址
  • 空指標值
(C++11 起)
(C++14 前)

下列實體是常數運算式的許可結果 

常數運算式或是指涉一個作為常數運算式許可結果之實體的廣義左值 (glvalue) 核心常數運算式,或是其值滿足下列約束的純右值核心常數運算式

  • 具有靜態儲存期物件的位址
  • 具有靜態儲存期物件尾端之後的位址
  • 非立即(自 C++20 起) 函式的位址
  • 空指標值
  • 若值為成員函式指標型別,則不代表立即函式。
(自 C++20 起)
  • 若值是類別或陣列型別物件,則每個子物件皆須滿足這些約束。
(C++14 起)
(直到 C++26)

常數運算式或是指涉一個物件或非立即函式的廣義左值 核心常數運算式,或是其值滿足下列約束的純右值核心常數運算式

(C++26 起)

在判定運算式是否為常數運算式時,假設不執行複寫消除 (copy elision)

C++98 的常數運算式定義完全包含在摺疊框內。以下描述適用於 C++11 及更高版本的 C++。

[編輯] 常值型別 (Literal type)

下列型別統稱為常值型別 

  • 具有 顯微解構子(至 C++20)constexpr 解構子(自 C++20 起)
  • 其所有非靜態且非變體 (non-variant) 資料成員及基底類別皆為非 volatile 常值型別。
  • 為下列型別之一
(自 C++17 起)
  • 沒有變體成員
  • 具有至少一個非 volatile 常值型別的變體成員。
  • 非聯集聚合型別,且其每個匿名聯集成員皆滿足下列條件之一
  • 沒有變體成員。
  • 具有至少一個非 volatile 常值型別的變體成員。
  • 具有至少一個不是複寫或移動構造函式的 constexpr 構造函式(模板)的型別

只有常值型別的物件可以在常數運算式中建立。

[編輯] 核心常數運算式

核心常數運算式是求值過程不會求值下列任何語言結構的任何運算式

語言結構     版本     提案論文 (Papers)
this 指標,除非是在作為運算式一部分求值的 constexpr 函式中,或者出現於隱式或顯式類別成員存取運算式中 N2235
通過具有靜態或執行緒 儲存期 且並非 可用於常數運算式區塊變數 聲明的控制流程 (自 C++23 起) P2242R3
  1. 呼叫未聲明為 constexpr 函式(或構造函式)的函式呼叫運算式
    constexpr int n = std::numeric_limits<int>::max(); // OK: max() is constexpr
    constexpr int m = std::time(nullptr); // Error: std::time() is not constexpr
  2. 呼叫已聲明但未定義的 constexpr 函式
  3. 呼叫不滿足 constexpr 函式/構造函式 要求的 constexpr 函式/構造函式模板具現化
  4. 呼叫 constexpr 虛擬函式,且呼叫該函式的物件之動態型別為 constexpr-unknown
  5. 會超出實作定義限制的運算式
  6. 其求值導致任何形式的核心語言 未定義 或錯誤(自 C++26 起) 行為的運算式,但由 標準屬性 引入的任何潛在未定義行為除外
    constexpr double d1 = 2.0 / 1.0; // OK
    constexpr double d2 = 2.0 / 0.0; // Error: not defined
    constexpr int n = std::numeric_limits<int>::max() + 1; // Error: overflow
    int x, y, z[30];
    constexpr auto e1 = &y - &x;        // Error: undefined
    constexpr auto e2 = &z[20] - &z[3]; // OK
    constexpr std::bitset<2> a; 
    constexpr bool b = a[2]; // UB, but unspecified if detected
  7. (至 C++17) lambda 運算式
  8. 左值轉右值 隱式轉換,除非套用於...
    1. (可能具有 cv 限定)型別為 std::nullptr_t 的廣義左值
    2. 代表 可用於常數運算式 之物件的非 volatile 常值型別廣義左值
      int main()
      {
          const std::size_t tabsize = 50;
          int tab[tabsize]; // OK: tabsize is a constant expression
                            // because tabsize is usable in constant expressions
                            // because it has const-qualified integral type, and
                            // its initializer is a constant initializer
       
          std::size_t n = 50;
          const std::size_t sz = n;
          int tab2[sz]; // Error: sz is not a constant expression
                        // because sz is not usable in constant expressions
                        // because its initializer was not a constant initializer
      }
    3. 指涉一個生命週期始於此運算式求值過程中的非 volatile 物件的非 volatile 常值型別廣義左值
  9. 聯集 的非活動成員或其子物件套用的左值轉右值隱式轉換或修改(即使它與活動成員共享共同的初始序列)
  10. 值為不確定 的物件套用左值轉右值隱式轉換
  11. 在生命週期始於此運算式求值之外的情況下,對活動成員為可變 (mutable) 的聯集(若有)呼叫隱式複寫/移動構造函式/賦值運算子
  12. (至 C++20) 會改變聯集活動成員的賦值運算式
  13. 指向 void 的指標 到物件指標型別 T* 的轉換,除非指標保存空指標值或指向型別與 T 相似 的物件(自 C++26 起)
  14. dynamic_cast 且運算元是個指涉動態型別為 constexpr-unknown 物件的廣義左值(自 C++20 起)
  15. reinterpret_cast
  16. (至 C++20) 偽解構子 (pseudo-destructor) 呼叫
  17. (至 C++14) 遞增或遞減運算子
  18. (自 C++14 起) 修改物件,除非該物件具有非 volatile 常值型別且其生命週期始於運算式的求值過程中
    constexpr int incr(int& n)
    {
        return ++n;
    }
     
    constexpr int g(int k)
    {
        constexpr int x = incr(k); // Error: incr(k) is not a core constant
                                   // expression because lifetime of k
                                   // began outside the expression incr(k)
        return x;
    }
     
    constexpr int h(int k)
    {
        int x = incr(k); // OK: x is not required to be initialized
                         // with a core constant expression
        return x;
    }
     
    constexpr int y = h(1); // OK: initializes y with the value 2
                            // h(1) is a core constant expression because
                            // the lifetime of k begins inside the expression h(1)
  19. (自 C++20 起) 對於生命週期非始於此運算式求值過程中的物件進行解構子呼叫或偽解構子呼叫
  20. 套用於多型型別廣義左值的 typeid 運算式,且該廣義左值指涉一個動態型別為 constexpr-unknown 的物件(自 C++20 起)
  21. new 運算式,除非滿足下列條件之一:(自 C++20 起)
    • 所選的 配置函式 是可替換的全域配置函式,且所配置的儲存空間在此運算式求值過程中被歸還。
    (自 C++20 起)
    • 所選的配置函式是非配置形式 (non-allocating form) 且配置型別為 T,且配置引數滿足下列所有條件
    • 它指向:
    • 一個型別與 T 相似的物件(若 T 不是陣列型別),或
    • 一個型別與 T 相似之物件的第一個元素(若 T 是陣列型別)。
    • 它指向一個生命週期始於此運算式求值過程中的儲存空間。
    (C++26 起)
  22. delete 運算式,除非它歸還在此運算式求值過程中配置的儲存區域(自 C++20 起)
  23. (自 C++20 起) 協程 (Coroutines):await-運算式yield-運算式
  24. (自 C++20 起) 當結果未指定時的 三路比較 (three-way comparison)
  25. 結果未指定的相等或關聯運算子
  26. (至 C++14) 賦值或複合賦值運算子
  27. (至 C++26) throw 運算式
  28. (自 C++26 起) 異常物件的構造,除非該異常物件及其所有經由呼叫 std::current_exceptionstd::rethrow_exception 建立的隱式複本皆在此運算式求值過程中被銷毀
    constexpr void check(int i)
    {
        if (i < 0)
            throw i;
    }
     
    constexpr bool is_ok(int i)
    {
        try {
            check(i);
        } catch (...) {
            return false;
        }
        return true;
    }
     
    constexpr bool always_throw()
    {
        throw 12;
        return true;
    }
     
    static_assert(is_ok(5)); // OK
    static_assert(!is_ok(-1)); // OK since C++26
    static_assert(always_throw()); // Error: uncaught exception
  29. asm-聲明
  30. 呼叫 va_arg 巨集
  31. goto 語句
  32. 會拋出異常的 dynamic_casttypeid 運算式 new 運算式(自 C++26 起)且該異常型別的定義不可達(自 C++26 起)
  33. 在 lambda 運算式內部,對 this 或對定義於該 lambda 外部之變數的參考,若該參考構成 odr-use
    void g()
    {
        const int n = 0;
     
        constexpr int j = *&n; // OK: outside of a lambda-expression
     
        [=]
        {
            constexpr int i = n;   // OK: 'n' is not odr-used and not captured here.
            constexpr int j = *&n; // Ill-formed: '&n' would be an odr-use of 'n'.
        };
    }

    請注意,若 ODR-use 發生在對閉包的函式呼叫中,它不指涉 this 或外圍變數,因為它存取的是閉包的資料成員

    // OK: 'v' & 'm' are odr-used but do not occur in a constant-expression
    // within the nested lambda
    auto monad = [](auto v){ return [=]{ return v; }; };
    auto bind = [](auto m){ return [=](auto fvm){ return fvm(m()); }; };
     
    // OK to have captures to automatic objects created during constant expression evaluation.
    static_assert(bind(monad(2))(monad)() == monad(2)());
    (自 C++17 起)

[編輯] 額外要求

即使運算式 E 沒有求值上述任何內容,若求值 E 會導致 執行時期未定義行為,則 E 是否為核心常數運算式是由實作定義的。

即使運算式 E 沒有求值上述任何內容,若求值 E 會求值下列任何內容,則 E 是否為核心常數運算式是未指定的

為了判斷運算式是否為核心常數運算式,若 T 是常值型別,則忽略 std::allocator<T> 成員函式本體的求值。

為了判斷運算式是否為核心常數運算式,對 聯集 的顯微複寫/移動構造函式或複寫/移動賦值運算子的呼叫,被視為複寫/移動該聯集的活動成員(若有)。

為了判斷運算式是否為核心常數運算式,對命名 結構化綁定 bd 的識別字運算式的求值具有下列語意

  • bd 是指涉到綁定於虛構參考 ref 之物件的左值,其行為如同提到了 ref
  • 否則,若 bd 命名陣列元素,其行為等同於求值 e[i],其中 e 是從結構化綁定聲明的初始化程式所初始化的變數名稱,而 i 是由 bd 指涉的元素索引。
  • 否則,若 bd 命名類別成員,其行為等同於求值 e.m,其中 e 是從結構化綁定聲明的初始化程式所初始化的變數名稱,而 m 是由 bd 指涉的成員名稱。
(C++26 起)

在將運算式作為核心常數運算式求值期間,所有指涉生命週期始於運算式求值之外的物件或參考的識別字運算式及 *this 的使用,皆被視為指涉該物件或參考的特定實例,其生命週期及所有子物件(包括所有聯集成員)的生命週期皆涵蓋整個常數求值過程。

  • 對於此類並非可用於常數運算式(自 C++20 起)的物件,物件的動態型別為 constexpr-unknown
  • 對於此類並非可用於常數運算式(自 C++20 起)的參考,該參考被視為綁定到一個所參考型別的未指定物件,該物件其生命週期及所有子物件的生命週期皆涵蓋整個常數求值過程,且其動態型別為 constexpr-unknown。

[編輯] 整數常數運算式

整數常數運算式是一個隱式轉換為純右值的整數或無作用域列舉型別的運算式,其中轉換後的運算式是個核心常數運算式。

若在需要整數常數運算式的地方使用了類別型別運算式,則該運算式會按語境隱式轉換為整數或無作用域列舉型別。

[編輯] 經轉換的常數運算式

型別 T經轉換常數運算式是個隱式轉換為型別 T 的運算式,其中轉換後的運算式是個常數運算式,且隱式轉換序列僅包含

(自 C++17 起)

此外,若發生任何參考綁定,它必須是直接綁定

下列語境需要經轉換的常數運算式

(C++14 起)
(C++26 起)

型別為 bool 的語境轉換常數運算式是個按語境轉換為 bool 的運算式,其中轉換後的運算式是常數運算式,且轉換序列僅包含上述轉換。

下列語境需要型別為 bool 的語境轉換常數運算式

(至 C++23 止)
(自 C++17 起)
(至 C++23 止)
(自 C++20 起)


構成實體 (Constituent entities)

物件 obj構成值 (constituent values) 定義如下

  • obj 是純量型別,其構成值即為 obj 的值。
  • 否則,其構成值為 obj非活動聯集成員外的任何直接 子物件 的構成值。

物件 obj構成參考 (constituent references) 包括下列參考

  • obj 的任何具有參考型別的直接成員
  • obj 除非活動聯集成員外任何直接子物件的構成參考

變數 var構成值構成參考定義如下

  • var 聲明一個物件,其構成值與參考即為該物件的構成值與參考。
  • var 聲明一個參考,其構成參考即為該參考。

對於變數 var 的任何構成參考 ref,若 ref 綁定到暫時物件(或其子物件)且該暫時物件的生命週期延長至 ref 的生命週期,則該暫時物件的構成值與參考也遞迴地成為 var 的構成值與參考。

可經由 Constexpr 表示的實體

具有靜態儲存期的物件在程式中任何位置皆為 constexpr-referenceable

具有自動儲存期的物件 obj 在位置 Pconstexpr-referenceable,條件是包圍變數 var 的最小作用域 (scope) 與包圍 P 的最小作用域是同一個函式參數作用域,且該作用域不與 requires 運算式的參數列表關聯,其中 var 是對應到 obj 的完整物件之變數,或者是其生命週期經由 obj 延長的變數。

物件或參考 x 在位置 P可經由 constexpr 表示的,條件是滿足下列所有條件

  • 對於 x 中指向物件 obj 的每個構成值,objP 點皆為 constexpr-referenceable。
  • 對於 x 中指向物件 obj 尾端之後的每個構成值,objP 點皆為 constexpr-referenceable。
  • 對於 x 指涉到物件 obj 的每個構成參考,objP 點皆為 constexpr-referenceable。
(C++26 起)

常數初始化的實體

變數或暫時物件 obj常數初始化的,條件是滿足下列所有條件

(直到 C++26)

變數 var可經由常數初始化的,條件是滿足下列所有條件

  • 其初始化的全運算式 在要求常數運算式的語境中是個常數運算式,其中所有契約斷言 (contract assertions) 皆使用「忽略」求值語意。
  • var 的初始化聲明之後,由 var 聲明的物件或參考是可經由 constexpr 表示的。
  • 若由 var 聲明的物件或參考 x 具有靜態或執行緒儲存期,則 x 在緊接著 var 初始化聲明之後、且其直接作用域為命名空間作用域的最近點,必須是可經由 constexpr 表示的。

一個可經由常數初始化的變數是常數初始化的,條件是它具有初始化程式,或者其型別為 const-預設可構造

(C++26 起)

可用於常數運算式

變數是潛在常數 (potentially-constant),若它是 constexpr 變數,或者它具有參考型別、或具有非 volatile const 限定的整數或列舉型別。

常數初始化的潛在常數變數 var 在位置 P 可用於常數運算式,條件是 var 的初始化聲明 DP 是可達的,且滿足下列任一條件

  • var 是一個 constexpr 變數。
  • var 並非初始化為 編譯單元本地 (TU-local) 的值。
  • PD 在同一個翻譯單元 (translation unit) 中。

物件或參考在位置 P可用於常數運算式的,若它是下列實體之一

  • P 點可用於常數運算式的變數
  • 非 volatile const 限定常值型別的暫時物件,其生命週期延長到在 P 點可用於常數運算式的變數之生命週期
  • 模板參數物件
  • 字串常值物件
  • 上述任何項目的非 mutable 子物件
  • 上述任何項目的參考成員
(直到 C++26)

物件或參考在位置 P潛在可用於常數運算式的,若它是下列實體之一

  • P 點可用於常數運算式的變數
  • 非 volatile const 限定常值型別的暫時物件,其生命週期延長到在 P 點可用於常數運算式的變數之生命週期
  • 模板參數物件
  • 字串常值物件
  • 上述任何項目的非 mutable 子物件
  • 上述任何項目的參考成員

物件或參考在位置 P可用於常數運算式的,條件是該物件或參考在 P 點是潛在可用於常數運算式的,且在 P 點是可經由 constexpr 表示的。

(C++26 起)

顯明常數求值的運算式 (Manifestly constant-evaluated expressions)

下列運算式(包括向目標型別的轉換)是顯明常數求值的 (manifestly constant-evaluated) 

求值是否發生在顯明常數求值的語境中,可藉由 std::is_constant_evaluated if consteval(自 C++23 起) 來檢測。

(自 C++20 起)

[編輯] 常數求值所需的函式與變數

下列運算式或轉換是潛在常數求值的 (potentially constant evaluated)

函式是常數求值所需的,若它是個 constexpr 函式,且被一個潛在常數求值的運算式所命名

變數是常數求值所需的,若它是個 constexpr 變數,或者它具有非 volatile const 限定的整數型別或參考型別,且表示它的識別字運算式是潛在常數求值的。

若函式或變數(自 C++14 起)是常數求值所需的,則會觸發預設函式的定義與函式模板特化變數模板特化(自 C++14 起)的具現化。

[編輯] 常數子運算式

常數子運算式是一個運算式,將其作為運算式 e子運算式進行求值時,不會阻止 e 成為核心常數運算式,其中 e 不是下列任何運算式

(自 C++20 起)

[編輯] 註解

特性測試巨集 數值 標準 功能
__cpp_constexpr_in_decltype 201711L (C++20)
(DR11)
常數求值需要時生成函式與變數定義
__cpp_constexpr_dynamic_alloc 201907L (C++20) constexpr 函式中用於動態儲存期的操作
__cpp_constexpr 202306L (C++26) void*constexpr 轉換:邁向 constexpr 型別擦除
202406L (C++26) constexpr placement newnew[]
__cpp_constexpr_exceptions 202411L (C++26) constexpr 異常

[編輯] 範例

[編輯] 缺陷報告

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

DR 應用於 出版時的行為 正確的行為
CWG 94 C++98 算術常數運算式原先不能
涉及變數與靜態資料成員
它們可以
CWG 366 C++98 涉及字串常值的運算式
可以作為整數常數運算式
它們不是
CWG 457 C++98 涉及 volatile 變數的運算式
可以作為整數常數運算式
它們不是
CWG 1293 C++11 原先不清楚字串常值是否
可用於常數運算式
現規定為可用
CWG 1311 C++11 volatile 廣義左值可用於常數運算式 禁止
CWG 1312 C++11 在常數運算式中禁止使用 reinterpret_cast
但轉換到 void* 以及從中轉換回來可達到相同效果
禁止下列轉換
從型別 cv void* 轉換到
物件指標型別
CWG 1313 C++11 原先許可未定義行為;
且禁止所有指標相減
現禁止未定義行為;且同陣列
指標相減改為許可
CWG 1405 C++11 對於可用於常數運算式的物件,
原先規定其可變 (mutable) 子物件亦可用
現改為不可用
CWG 1454 C++11 原先不允許通過參考將常數
傳遞給 constexpr 函式
已允許
CWG 1455 C++11 經轉換常數運算式原先只能是純右值 現可為左值
CWG 1456 C++11 位址常數運算式原先不能
表示陣列尾端之後一個位置的位址
已允許
CWG 1535 C++11 其運算元為
多型類別型別的 typeid 運算式原先不視為核心常數
運算式,即使不涉及執行時期檢查
現運算元約束
僅限於多型
類別型別的廣義左值
CWG 1581 C++11 常數求值所需的函式原先
不要求必須定義或具現化
現在要求必須能互相比較
CWG 1613 C++11 核心常數運算式原先可求值 lambda 運算式內部
任何經 ODR-used 的參考
現規定某些參考
不能被求值
CWG 1694 C++11 將暫時物件的值綁定到靜態儲存
期參考原先被視為常數運算式
現改為不視為
常數表達式
CWG 1872 C++11 核心常數運算式原先可呼叫不滿足
constexpr 函式要求的 constexpr 函式模板特化
現規定此類特化
不可被呼叫
CWG 1952 C++11 標準函式庫的未定義行為
原先要求必須診斷
現改為是否診斷
由實作指定
CWG 2022 C++98 常數運算式的判定原先可能
取決於是否執行複寫消除
現規定假設複寫消除
總是會執行
CWG 2126 C++11 常數初始化的生命週期延長、具有 const 限定
常值型別的暫時物件原先不能用於常數運算式
現規定為可用
CWG 2129 C++11 整數常值原先不視為常數運算式 它們是
CWG 2167 C++11 對求值而言為局部的非成員參考
原先會使求值變為非 constexpr
現改為允許
非成員參考
CWG 2278 C++98 CWG 問題 2022 的決議無法實作 現規定假設複寫消除
現假設為永不執行
CWG 2299 C++14 原先不清楚 <cstdarg> 中的巨集
是否可用於常數求值
現禁止 va_arg
va_start 未指定
CWG 2400 C++11 對不可用於常數運算式且生命週期始於求值外之物件
呼叫 constexpr 虛擬函式原先可能是常數運算式
(現已修正)
現改為不視為
常數表達式
CWG 2490 C++20 (偽)解構子呼叫在常數求值中原先欠缺
約束條件
現已加入約束
CWG 2552 C++23 當求值核心常數運算式時,控制流
原先不得通過非區塊變數的聲明
現在可以
CWG 2558 C++11 不確定值原先可能是常數運算式 現改為不是常數運算式
CWG 2647 C++20 具有 volatile 限定型別的變數原先可能為潛在常數 它們不是
CWG 2763 C++11 違反 [[noreturn]] 的行為原先不要求
必須在常數求值期間被檢測
現在要求必須能互相比較
CWG 2851 C++11 經轉換常數運算式原先
不允許浮點數轉換
現允許非窄化
浮點數轉換
CWG 2907 C++11 核心常數運算式原先不能對
std::nullptr_t 廣義左值套用左值轉右值轉換
現可套用
轉換
CWG 2909 C++20 不具初始化程式的變數原先只有當其預設初始化
會執行某些初始化操作時才能
進行常數初始化
現規定僅在其型別為
const-預設可初始化時
才能進行常數初始化
CWG 2924 C++11
C++23
原先未指定違反 [[noreturn]] (C++11) 或
[[assume]] (C++23) 約束的運算式
是否為核心常數運算式
現在是了
實作定義的
P2280R4 C++11 原先求值包含指涉到生命週期始於此求值外之物件或
參考的識別字運算式或 *this 的運算式
並非常數運算式
現規定可以作為常數運算式
常數表達式

[編輯] 參閱

constexpr 說明符(C++11) 指定變數或函數的值可以在編譯期計算[編輯]
(C++11)(於 C++17 中棄用)(於 C++20 中移除)
檢查型別是否為字面量 (literal) 型別
(類別模板) [編輯]
C 語言文件常數運算式
English Deutsch 日本語 中文(简体) 中文(繁體)