I have a generic structure in rust that has one general field, in this case val and a type specific field:
struct A<T> {
val: i32,
t: T
}
What I am trying to do is to have a method associated to the struct regardless the type T. Something that I can call like this:
A::my_method()
Instead of:
A::<T>::my_method()
I tried implementing a trait called Get on A<T> and call it as follows:
struct A<T> {
val: i32,
t: T
}
trait Get {
type ValType;
fn get_val() -> Self::ValType;
}
impl<T> Get for A<T> {
type ValType = i32;
fn get_val() -> Self::ValType {
2
}
}
fn main() {
let a = A {
val: 2,
t: 3.0
};
// This is the call I want, if possible
println!("{:?}", A::get_val());
}
The issue is that it doesn't compile, which is to be expected. The outcome I want is something like this:
impl<T> Get for A<any T> {
type ValType = i32;
fn get_val() -> Self::ValType {
2
}
}
I found on some posts that a workaround is to have a dummy type parameter and call my function as this:
struct DummyType;
fn main() {
let a = A {
val: 2,
t: 3.0
};
// This is the call I want, if possible
println!("{:?}", A::<DummyType>::get_val());
}
CodePudding user response:
First, your design looks wrong. If the type is generic, what does it mean to have a non-generic method?
Anyway, you can use a sentinel type (and you don't need a trait for that, I don't really get why you put it in the first place):
impl A<()> {
fn get_val() -> i32 {
2
}
}
The compiler infers T
to be ()
automatically when you call A::get_val()
.
CodePudding user response:
What you are probably missing is a method receiver.
pub struct A<T> {
pub field: usize,
pub something: T,
}
pub trait Getter {
type Output;
fn get(&self) -> Self::Output;
}
impl<T> Getter for A<T> {
type Output = usize;
fn get(&self) -> Self::Output {
self.field
}
}
fn main() {
let a = A { field: 10, something: 3.0 };
assert_eq!(a.get(), 10);
}
Here you can return the state of A
and not just constant.
CodePudding user response:
Fine, I tried this and rust seems to be okay with it:
pub trait Get {
type Output;
fn get() -> Self::Output;
}
pub struct A<T>(T);
impl Get for A<()> {
type Output = usize;
fn get() -> Self::Output {
2
}
}
fn main() {
println!("{}", A::get());
}
The ()
is the best pick here as you want to express that parameter is not important to us here but also not declare a type just for that.