Jonathan Woollett-light
Jonathan Woollett-light

Reputation: 3243

Return non-array types based off const generic

I know it is possible to return different types based off a const generic e.g. fn example<const N:usize>() -> [u8;N].

Is it possible to return generic types based off a const generic e.g. fn example<const N:usize>() -> N::Type?

My best attempt at the moment (playground):

struct MyStruct {
    first: First,
    second: Second,
    third: Third
}
impl MyStruct {
    fn first(&self) -> &First {
        &self.first
    }
    fn second(&self) -> &Second {
        &self.second
    }
    fn third(&self) -> &Third {
        &self.third
    }
}
#[derive(Debug)]
struct First(u16);
#[derive(Debug)]
struct Second(u8);
#[derive(Debug)]
struct Third(u32);

trait ConstIndex<const INDEX:usize> {
    type Output;
    fn index(&self) -> &Self::Output;
}
impl ConstIndex<0> for MyStruct {
    type Output = First;
    fn index(&self) -> &Self::Output {
        self.first()
    }
}
impl ConstIndex<1> for MyStruct {
    type Output = Second;
    fn index(&self) -> &Self::Output {
        self.second()
    }
}
impl ConstIndex<2> for MyStruct {
    type Output = Third;
    fn index(&self) -> &Self::Output {
        self.third()
    }
}

fn main() {
    let my_struct = MyStruct { first: First(123), second: Second(242), third: Third(789) };
    let one = ConstIndex::<0>::index(&my_struct);
    println!("one: {:?}",one);
    let two = ConstIndex::<1>::index(&my_struct);
    println!("two: {:?}",two);
    let three = ConstIndex::<2>::index(&my_struct);
    println!("three: {:?}",three);
    
}

The syntax here for indexing is awkward e.g. ConstIndex::<2>::index(&my_struct).

It would be preferable to use syntax like my_struct.cindex::<0>().

Upvotes: 1

Views: 46

Answers (1)

phimuemue
phimuemue

Reputation: 35983

I think you're looking for something like this:

playground

struct MyStruct {
    first: First,
    second: Second,
    third: Third
}
impl MyStruct {
    fn first(&self) -> &First {
        &self.first
    }
    fn second(&self) -> &Second {
        &self.second
    }
    fn third(&self) -> &Third {
        &self.third
    }
    
    fn cindex<const N:usize>(&self) -> &<MyStruct as ConstIndex<N>>::Output
        where MyStruct : ConstIndex<N>
    {
        <MyStruct as ConstIndex<N>>::index(self)
    }
}
#[derive(Debug)]
struct First(u16);
#[derive(Debug)]
struct Second(u8);
#[derive(Debug)]
struct Third(u32);

trait ConstIndex<const INDEX:usize> {
    type Output;
    fn index(&self) -> &Self::Output;
}
impl ConstIndex<0> for MyStruct {
    type Output = First;
    fn index(&self) -> &Self::Output {
        self.first()
    }
}
impl ConstIndex<1> for MyStruct {
    type Output = Second;
    fn index(&self) -> &Self::Output {
        self.second()
    }
}
impl ConstIndex<2> for MyStruct {
    type Output = Third;
    fn index(&self) -> &Self::Output {
        self.third()
    }
}

fn main() {
    let my_struct = MyStruct { first: First(123), second: Second(242), third: Third(789) };
    let one = ConstIndex::<0>::index(&my_struct);
    println!("one: {:?}",one);
    let two = ConstIndex::<1>::index(&my_struct);
    println!("two: {:?}",two);
    let three = ConstIndex::<2>::index(&my_struct);
    println!("three: {:?}",three);
    
    let one_2 = my_struct.cindex::<0>();
    println!("one: {:?}",one_2);
    let two_2 = my_struct.cindex::<1>();
    let three_2 = my_struct.cindex::<2>();
}

Upvotes: 1

Related Questions