Home > Blockchain >  Trait or method that does not depend on generic type
Trait or method that does not depend on generic type

Time:03-23

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().

Playground.

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.

  • Related