[英]Are tautologies in compile-time evaluated code guaranteed to be executed / optimized away?
編譯器是否保證在constexpr
環境中評估"tautologies"
(例如,始終分別為true
或false
)的布爾型constexpr
表達式?
例如,在以下代碼片段中(在標有(1)
)我在constexpr
環境中調用一個函數,我打算在傳遞non-constexpr
函數時導致編譯時錯誤。 至少我使用的編譯器 ( g++-10.0
) 是這樣做的,即使它也可以意識到表達式始終為true
而不求值。 我問這個問題的原因是——據我所知——在非 constepxr 上下文中,像i >= std::numeric_limits<int>::min()
這樣的表達式被優化為true
for一個int i
。
#include <limits>
constexpr int example_function() { return 1;}
constexpr bool compileTimeErrorDesired = example_function() || true; // (1)
如果(1)
的行為得到保證,則它可以例如用於concept
,以執行不同的代碼,具體取決於作為模板參數提供的函數是否可以在編譯時求值。 我實現了一個非常短的( 7 lines-of-code
)示例,它在編譯器資源管理器中完全做到了這一點。
如果使用非 constexpr 函數調用,行 (1) 是否保證會導致編譯時錯誤?
編輯插入澄清,由於反饋而簡化示例。
保證f() || true
如果f
不是 constexpr 函數,則f() || true
不是核心常量表達式:(常量表達式比核心常量表達式更具限制性) [expr.const]/2.2
表達式
e
是核心常量表達式,除非e
的計算遵循抽象機器的規則,將計算以下表達式之一:
[...]
比constexpr構造為一個文字類,一個constexpr函數,或一個簡單的析構函數的隱式調用其它的函數的調用([class.dtor])[注:重載分析被用於像往常一樣-注完];
[...]
如果在需要常量表達式的上下文中使用非常量表達式,還可以保證程序格式錯誤(需要診斷)。 注意||
定義為從左到右計算: [expr.log.or]/1
||
運算符組從左到右。 操作數都根據上下文轉換為bool
。 如果其任一操作數為true
,則返回true
否則返回false
。 不像|
,||
保證從左到右的評估; 此外,如果第一個操作數的計算結果為真,則不會計算第二個操作數。
換句話說, true || f()
true || f()
是一個核心常量表達式,因為f()
不被計算,而f() || true
f() || true
不是因為f()
被評估。
表達式是否為常量表達式與優化無關——常量表達式是根據抽象機器的規則定義的。
當涉及到常量表達式時,術語“執行”並不完全合適。 甚至“求值”也可能要小心使用,因為表達式是否為常量表達式部分取決於如果對表達式求值會發生什么情況,但在最嚴格的意義上不被視為求值。
[expr.const]描述了“編譯時行為”的許多不同上下文的要求,包括“常量表達式”。 [expr.const]/(5.2) 表示如果計算表達式會計算非 constexpr 函數,則該表達式不是核心常量表達式,因此也不是常量表達式。 如果在需要常量表達式的上下文中使用表達式(如static_assert
、非類型模板參數等),則程序static_assert
,並且必須有診斷消息。 沒有規則允許在這樣的上下文中允許非常量表達式或跳過假設評估的某些部分,如果表達式是轉換后的常量表達式,並且表達式的結果值可以確定,盡管它不是常量表達式。
因此,如果example_function
未聲明為constexpr
,則example_function() || true
example_function() || true
不是常量表達式,因為計算需要調用函數。 但true || example_function()
true || example_function()
是一個常量表達式,因為評估不會調用該函數。
您的is_constexpr<T>
保證可以工作,因為任何涉及requires-expression中的模板參數的語義約束違規都不會使程序格式false
,而只會使requires-expression結果值為false
( [expr.prim.req ]/6 )。 在is_constexpr<example_function>
,通過ConstexprHelper<T>
實例化的默認模板參數使用非常量表達式T()
作為std::enable_if
的模板參數是這樣的語義錯誤,因此requires-expression 的值為false
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.