Reputation: 48248
I'm writing some code in Rust which can work equally as well with f64
and f32
.
Attempting to convert this to use generic functions is quite involved; I need to declare the capabilities of the type on every use.
In practice, I only want f32
and f64
to be used. Is there a way to write generic functions that only apply to a set of known types?
I realize this goes against generic functions a little.
Upvotes: 7
Views: 1348
Reputation: 2080
It might not be ideal, but I accomplish this by using a trait and a macro.
For example, say we want this function to take either f32
or f64
:
fn sqr(a: f32) -> f32 {
a * a
}
We can first put it in a trait:
trait Sqr {
fn sqr(self) -> Self;
}
Then we make a macro for implementing it. The macro just takes a type, and implements the trait for that type:
macro_rules! impl_sqr {
($t:ty) => (
impl Sqr for $t {
fn sqr(self) -> Self {
self * self
}
}
);
}
Then we call the macro for f32
and f64
:
impl_sqr!(f32);
impl_sqr!(f64);
Upvotes: 0
Reputation: 2002
Just use the Float
trait from the num crate. You’ll have anything you need for both f32
and f64
only. Do not write your own trait if you don’t really need to.
Just add the crate num-traits
into your [dependencies]
section of your Cargo.toml file to be able to use that trait:
[dependencies]
# ...
num-traits = "0.1"
Upvotes: 4
Reputation: 14051
The only tool that comes to mind for this is a trait
, so your function would be:
pub fn f<T: MyTrait>(x: T) {...}
You could then implement MyTrait
for f32
and f64
. This is close, but there's a hole: callers can implement the trait on their own types. You can't get around this by making MyTrait
private, since Rust then complains that you're using a private type (MyTrait
) in a public interface.
So close, but I don't think it's exactly possible!
Although I agree with the other answer about using an existing relevant trait, you would do it a bit like:
mod foo {
pub trait MyTrait {}
impl MyTrait for f32 {}
impl MyTrait for f64 {}
pub fn f<T: MyTrait>(x: T) {}
}
pub fn main() {
foo::f(3f32);
foo::f(3f64);
// foo::f(3u64); // doesn't work as u64 doesn't implement MyTrait
}
Upvotes: 3