Reputation: 474
When using this expression:
mem::size_of::<T>() * 8
Like this:
value % (mem::size_of::<T>() * 8);
value * (mem::size_of::<T>() * 8);
would the compiler be able to optimize it to this:
value & ((mem::size_of::<T>() * 8) - 1);
value >> LOG2_OF_EXPRESION;
Is there something equivalent to C++'s constexpr
so I can return it from a function and use it where a compile time expression would be expected?
Upvotes: 3
Views: 773
Reputation: 431589
mem::size_of
is now declared as a const
fn, which means that it is guaranteed to be able to be evaluated at compile time. You can make use of it in const contexts:
use std::mem;
const BYTES: usize = mem::size_of::<f64>();
fn main() {}
The only way to know for sure is to look at the LLVM IR or assembly. It is allowed for this to change over time, so if it's super important, you need to keep track of it yourself.
As of Rust 1.14, this code:
#![crate_type="lib"]
use std::mem;
pub fn use_it() -> usize {
mem::size_of::<String>() * 8
}
produces this LLVM IR when compiled in debug mode:
; Function Attrs: norecurse nounwind readnone uwtable
define i64 @_ZN10playground6use_it17h005e773511657405E() unnamed_addr #0 {
entry-block:
ret i64 192
}
As you can see, the call to size_of
has become the constant value 192
. Rust and/or LLVM are then able to do whatever normal optimization they want to.
I'd believe it is safe to assume that this function will always be a compile-time constant.
Is there something equivalent to C++'s
constexpr
See Equivalent of constexpr from C++?
Not yet. RFC 911 introduced const
functions, functions which are able to be evaluated at compile time. The trick is that actually enabling this for everything that it should work with is difficult and predicated on some internal rewriting of the compiler.
In nightly Rust, you can do something like:
#![feature(const_fn)]
const fn adder(a: usize, b: usize) -> usize {
a + b
}
const BITS: usize = adder(1, 2);
fn main() {
println!("{}", BITS);
}
Upvotes: 7