在编译时评估'mem :: size_of'吗?

时间:2016-12-23 18:53:32

标签: rust

使用此表达式时:

mem::size_of::<T>() * 8

像这样:

value % (mem::size_of::<T>() * 8);
value * (mem::size_of::<T>() * 8);

编译器是否能够将其优化为:

value & ((mem::size_of::<T>() * 8) - 1);
value >> LOG2_OF_EXPRESION;

是否有类似于C ++ constexpr的东西,所以我可以从函数返回它并在需要编译时表达式的地方使用它?

1 个答案:

答案 0 :(得分:6)

从Rust 1.22.0开始

mem::size_of现在被声明为const fn,这意味着它保证在编译时可以进行评估。您可以在const上下文中使用它:

use std::mem;

const BYTES: usize = mem::size_of::<f64>();

fn main() {}

在Rust 1.22.0之前

唯一可以确定的方法是查看LLVM IR或汇编。允许随着时间的推移而改变,所以如果它非常重要,你需要自己跟踪它。

从Rust 1.14开始,这段代码:

#![crate_type="lib"]

use std::mem;

pub fn use_it() -> usize {
    mem::size_of::<String>() * 8
}

调试模式下编译时生成此LLVM IR:

; Function Attrs: norecurse nounwind readnone uwtable
define i64 @_ZN10playground6use_it17h005e773511657405E() unnamed_addr #0 {
entry-block:
  ret i64 192
}

如您所见,对size_of的调用已成为常量值192。然后,Rust和/或LLVM可以执行他们想要的任何正常优化。

我相信可以安全地假设函数始终是编译时常量。

  

是否存在与C ++ constexpr

等效的内容

请参阅Equivalent of constexpr from C++?

还没有。 RFC 911引入了 const函数,这些函数可以在编译时进行评估。诀窍在于,实际上为它应该使用的所有东西启用它很困难,并且在编译器的一些内部重写上是预测的。

在夜间Rust中,您可以执行以下操作:

#![feature(const_fn)]

const fn adder(a: usize, b: usize) -> usize {
    a + b
}

const BITS: usize = adder(1, 2);

fn main() {
    println!("{}", BITS);
}