簡體   English   中英

C++ constexpr 表達式求值

[英]C++ constexpr expression evaluation

我對以下有關 constexpr 函數中使用的條件表達式的評論有疑問:

不計算 constexpr 函數中未采用的條件表達式的分支。 來源: 函數的條件評估

正如源代碼中已經寫的那樣,您可以使用 constexpr 函數,例如

constexpr int check(int i) {
    return (0<=i && i<10) ? i : throw out_of_range();
}

並且僅評估所采用的分支。 到現在為止還挺好。 但是為什么這與模板結合使用無效。 所以讓我們在這里拿這個基本的例子:

template <int N>
constexpr int times(int y) {
    return (N<0) ? 0 : y+times<N-1>(y);
}

times<5>(10);

編譯失敗是因為模板實例化深度超過了最大值,即使條件的false分支只取了 4 次。 然后它應該采用true分支並返回 0。當然它可以使用enable_if或其他方法重寫,但我只想知道以下內容:

  • 當涉及到子表達式類型評估時,此語句是否無效?

  • 為什么即使上面的語句聲稱沒有計算子表達式,這也會失敗? 我想無論如何都必須評估類型(例如,檢查是否滿足條件的兩個分支具有相同類型的要求),因此它以無限模板實例化結束。 正確的假設?

  • c++ 標准中是否有描述這種行為的地方?

您誤解了評估某事的含義。 評估是在執行時發生的事情(即使該執行發生在編譯器運行時)。

模板實例化是代碼的靜態屬性。 如果您編寫times<N-1>您要求實例化該模板。 是否調用該函數並不重要; 您編寫實例化,因此它被實例化。

這就是遞歸元編程通常通過模板特化處理終端情況的原因。

這就是為什么if constexpr添加到 C++17 的原因。 因為它有能力,不僅有條件地評估語句,而且有條件地丟棄語句,使另一個分支實際上不存在。 這是以前不存在的東西。 這允許另一個分支包含否則會被靜態地錯誤形成的代碼。

所以這會起作用:

if constexpr(N < 0) return 0 else return y+times<N-1>(y);

第二個子句將被丟棄,因此不會被實例化。

所以這個說法是正確的; 子表達式是有條件地求值的。 您只是誤解了它如何適用於您的案例。

暫無
暫無

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

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