在Rust中,是否有可能检查一个值是编译时常量?

4

有时内联函数或宏展开出大量代码。然而,当与常量一起使用时,无用的分支可以被优化掉。

我可以在代码中添加注释:

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

不过我更希望添加某种静态断言来确保这种情况始终存在。

在Rust中,是否有一种方法可以检查一个值是否是编译时常量?

类似于GCC的__builtin_constant_p吗?

2个回答

5

如果值或表达式的类型是固定且预先已知的,则可以定义一个本地常量并用该值或表达式初始化它。如果您不使用该常量,可以在其名称前加下划线以抑制编译器关于未使用该常量的警告。但这仅适用于宏。

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

1

添加到 @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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接