I am currently writing code which is intended to become a highly-optimized library later on.
One of these intended optimizations are Const Generics, in order to compile away branches and avoid potential mispredictions during runtime and unnecessary calls/instructions.
To give some more context, the struct I am about to post is intended to be used in either a cached or non-cached mode (the latter always reading from the file, which is higher IO).
Both variants must be instantiable, because I need that for the planned CLI tool.
My old implementation was this:
pub struct MPQ {
file: Option<File>,
cache: Option<Vec<u8>>,
// other members and functions
}
This of course requires checking cache
at runtime if it is Some
and also unwrap()
.
I already know that I can rewrite it as this, which allows me to optimize away the if statement at least, by using CACHED
as expression:
pub struct MPQ<const CACHED: bool> {
file: Option<File>,
cache: Option<Vec<u8>>,
// other members and functions
}
What I would like to also get rid of is Option
, so I do not have to unwrap()
.
// when CACHED is false, the struct only has file
pub struct MPQ<const CACHED: bool> {
file: File,
// other members and functions
}
// when CACHED is true, the struct only has cache
pub struct MPQ<const CACHED: bool> {
cache: Vec<u8>,
// other members and functions
}
I know it is also possible to use a generic type instead, to handle a member dynamically as File or Vec, but I would prefer the bool approach.
It is more ergonomic for me, but it is also more generic (hehe), since this could be used without a type required (turning behavior off and on).
Interestingly enough Rust already provides the cfg attribute, which allows dynamic members by defining custom features.
pub struct MPQ<const CACHED: bool> {
#[cfg(feature = "cached")]
cache: Vec<u8>,
// other members and functions
}
But I can not use that, since I need both variants at the same time in my code.
I don't understand why this is possible with features, but not const generics, as both are evaluated at compile time, no?
From what I understood, for the compiler MPQ<true>
and MPQ<false>
would be entirely different types, and thus can have a different set of members etc.
At least right now I do not see a reason why it is possible with one, but not the other.