Is there any way to define a function in Rust with a generically-typed argument which will either copy or (immutably) borrow the argument depending on whether its concrete type is a Copy
type? If that requires a macro, how might one go about writing such a macro–can they be invoked with knowledge of the concrete type being used at compile time?
My specific use case is to try to write a big codebase that’s generically defined for native, hardware-accelerated float types (especially f64) or for custom-defined exact-precision number types (especially rational numbers) without having to duplicate upwards of 95% of the code. I would like to avoid indirection for native types, and would like for non-native types (which may be much larger than a CPU register) to not be copied but also not moved and inaccessible after calling the function on them; otherwise, one of these cases will suffer a massive performance hit.
The stub below is obviously invalid Rust code but hopefully clarifies a little–I would like to be able to write the generic function foo
that involves, for example, adding numbers, with or without copy semantics depending on the number type–and if foo
contains ten thousand such operations, I’d really like to avoid duplicating all that logic.
trait Scalar {}
trait CopiedScalar: Scalar {
fn plus(self, other: Self) -> Self;
}
trait NonCopiedScalar: Scalar {
fn plus(&self, other: &Self) -> Self;
}
fn foo<S: Scalar>(s1: S, s2: S) -> S {
s1.plus(s2) // compile error! obviously not even valid for NonCopiedScalar
}
1