Is there a way to apply Rust's feature flag support to function parameters? I have a function which takes bunch of inputs, but one of the inputs should only be passed if a feature is active. Of course I can make that parameter optional like:
pub fn my_function(input1: usize, input2: String, input3: Option<Vec<u32>>) -> () {...}
But is there a way to instead make use of the feature flag and define something like this?:
pub fn my_function(
input1: usize,
input2: String,
#[cfg(feature = "my-feature")]
input3: Vec<u32>
) -> () {...}
Similarly, later calling it as: my_function(0, "", #[cfg(feature = "my-feature")] vec![0])?
Rust's feature flags are a thin wrapper around conditional compilation. Imagine how you'd write your code if the feature were always enabled, then again if it were always disabled, and wrap the lines that differ between the two with #[cfg(..]) expressions. To define a function that differs, you can define two different versions and have them call a shared inner block if they're nearly the same, or just define them separately if they should do different things:
struct Thing;
impl Thing {
#[cfg(not(feature = "my-feature"))]
pub fn my_function(input1: usize, input2: String) {
Thing::my_function_inner(input1, input2, None);
}
#[cfg(feature = "my-feature")]
pub fn my_function(input1: usize, input2: String, input3: Vec<u32>) {
Thing::my_function_inner(input1, input2, Some(input3));
}
#[inline]
fn my_function_inner(input1: usize, input2: String, input3: Option<Vec<u32>>) {
todo!();
}
}
Alternatively, you can simply tag the conditional argument with a cfg expression and use conditional compilation within the function body:
impl Thing {
pub fn my_function(
input1: usize,
input2: String,
#[cfg(feature = "my-feature")] input3: Vec<u32>,
) {
// common implementation
#[cfg(feature = "my-feature")]
{ /* `input3` is only available when feature is enabled */ }
#[cfg(not(feature = "my-feature"))]
{ /* only run when feature is disabled */ }
}
}
Choose whichever makes the most sense for your use case. The compiler will likely optimize them similarly.
To call this, you can either rely on the feature flag always being enabled/disabled and just use the corresponding version, or you can include code for both like so:
fn main() {
#[cfg(not(feature = "my-feature"))]
Thing::my_function(0, "".to_string());
#[cfg(feature = "my-feature")]
Thing::my_function(0, "".to_string(), vec![0]);
}
EDIT: To support conditionally compiled return types, you can declare your return type to be a type alias that is itself conditionally compiled, like so:
#[cfg(feature = "my-feature")]
type ReturnType = (usize, usize);
#[cfg(not(feature = "my-feature"))]
type ReturnType = (usize,);
fn my_function() -> ReturnType { todo!() }
Thanks to @ChayimFriedman and @Jmb.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With