有些情況下內聯函數或宏會擴展成很多代碼。但是,當與常量一起使用時,死分支可以被優化掉。可能檢查一個值是Rust中的編譯時間常量嗎?
我可以在代碼中添加評論:
// foo arg is always a constant, dead branches will be removed
但我寧願添加某種靜態斷言,保證,這是總是如此。
Rust有沒有辦法檢查一個值是否是一個編譯時間常量?
像GCC的__builtin_constant_p
?
有些情況下內聯函數或宏會擴展成很多代碼。但是,當與常量一起使用時,死分支可以被優化掉。可能檢查一個值是Rust中的編譯時間常量嗎?
我可以在代碼中添加評論:
// foo arg is always a constant, dead branches will be removed
但我寧願添加某種靜態斷言,保證,這是總是如此。
Rust有沒有辦法檢查一個值是否是一個編譯時間常量?
像GCC的__builtin_constant_p
?
如果值或表達式的類型是預先確定並已知的,則可以定義一個局部常量並用該值或表達式對其初始化。如果不另外使用該常量,則使用下劃線前綴其名稱,以禁止關於常量未使用的編譯器警告。但是,這隻適用於宏。
const _ASSERT_COMPILE_TIME_CONSTANT: i32 = $arg;
每晚的編譯器也支持定義「const函數」,即可以在上下文,其中編譯器要求可以在編譯時被求值的表達式中使用,即功能。這些函數的主體受到限制,但在編譯時調用不需要進行評估的const函數的站點可以將在編譯時無法評估的表達式作爲參數傳遞,因此定義const函數不會提供保證你要求。
如果該值或表達式的類型不能在宏被指定,那麼我們不能省略它,作爲const
要求類型來指定。但是,我們可以使用一個通用const函數,它在const
初始值設定項中返回一個固定類型!
// at the beginning of the crate
#![feature(const_fn)]
// in the macro's body
const fn _swallow<T>(_x: T) {() }
const _ASSERT_COMPILE_TIME_CONSTANT:() = _swallow($arg);
要添加到@Francis答案,這是一個可以用來確保常數值的宏。
macro_rules! ensure_const_expr {
($value:expr, $t:ty) => {
{
const _IGNORE: $t = $value;
}
}
}
// in a functions body
ensure_const_expr!(some_variable, i32);
注意額外的括號所以需要多次使用不失敗:
error: a value named `_IGNORE` has already been defined in this block