2016-08-27 43 views
2

有些情況下內聯函數或宏會擴展成很多代碼。但是,當與常量一起使用時,死分支可以被優化掉。可能檢查一個值是Rust中的編譯時間常量嗎?

我可以在代碼中添加評論:

// foo arg is always a constant, dead branches will be removed 

但我寧願添加某種靜態斷言,保證,這是總是如此。

Rust有沒有辦法檢查一個值是否是一個編譯時間常量?

像GCC的__builtin_constant_p

回答

3

如果值或表達式的類型是預先確定並已知的,則可以定義一個局部常量並用該值或表達式對其初始化。如果不另外使用該常量,則使用下劃線前綴其名稱,以禁止關於常量未使用的編譯器警告。但是,這隻適用於宏。

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); 
0

要添加到@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 
相關問題