I want to have a trait that can be implemented for T and &T but has methods that always return T.
What I would like to do is something like this
use std::borrow::ToOwned;
trait Foo<X: ToOwned> {
fn f(&self, x: X) -> f64;
fn g(&self) -> X::Owned;
}
struct Float(f64);
impl Foo<f64> for Float {
fn f(&self, x: f64) -> f64 {
x + self.0
}
fn g(&self) -> f64 {
self.0 * 2.0
}
}
struct List(Vec<f64>);
impl Foo<&Vec<f64>> for List {
fn f(&self, x: &Vec<f64>) -> f64 {
x.iter().sum()
}
// Error here - `&Vec<f64>` return type expected
fn g(&self) -> Vec<f64> {
self.0.iter().map(|&x| 2.0 * x).collect()
}
}
fn main() {
let float = Float(2.0);
println!("{} {}", float.f(3.0), float.g());
let list = List(vec![0.0, 1.0, 2.0]);
println!("{} {:?}", list.f(&vec![1.0, 2.0]), list.g());
}
I know that one option is to have a trait that defines the output type like so
trait FooReturn {
type Output;
}
trait Foo<X: FooReturn> {
fn f(&self, x: X) -> f64;
fn g(&self) -> X::Output;
}
then implement the trait for all relevant types, but I was wondering if there was a more standard/robust way to do this.