I tried to make structure that contains tuple that has different size. Structure implements function get
that would return tuple created as shown in example.
// Passed tuple with four elements into macros
impl <A0, A1, A2, A3> Cont<(A0, A1, A2, A3)> {
fn get(&self) -> (A0, A1, A2, A3) {
(self.data.0, self.data.1, self.data.2, self.data.3)
}
}
// Passed tuple with five elements into macros
impl <A0, A1, A2, A3, A4> Cont<(A0, A1, A2, A3, A4)> {
fn get(&self) -> (A0, A1, A2, A3, A4) {
(self.data.0, self.data.1, self.data.2, self.data.3, self.data.4)
}
}
I'm not sure how to use cycle as A|number|
What you can or should do, is not care about the tuples. One generic parameter can cover all tuples, see this:
struct Foo<T> {
data: T,
}
impl<T> Foo<T> {
fn get(&self) -> &T {
&self.data
}
}
fn example() {
let foo = Foo { data: (1, "hello") };
assert_eq!(foo.get(), &(1, "hello"));
let foo = Foo {
data: (1, "hello", 2),
};
assert_eq!(foo.get(), &(1, "hello", 2));
}
If you want limit what type can hold, you usually do it with traits to keep common functions names.
macro_rules! impl_tuple {
($(
($($p:ident),*);
)*) => {
$(
impl<$($p),*> sealed::Sealed for ($($p,)*) {}
)*
};
}
mod sealed {
pub trait Sealed {}
}
pub trait ValidData: sealed::Sealed {}
impl<T: sealed::Sealed> ValidData for T {}
impl_tuple! {
(A);
(A, B, C);
(A, B, C, D, E);
}
struct Foo<T: ValidData> {
data: T,
}
impl<T: ValidData> Foo<T> {
fn get(&self) -> &T {
&self.data
}
}
fn main() {
let foo = Foo { data: 1 }; // fails
// the trait bound `{integer}: Sealed` is not satisfied
// the following other types implement trait `Sealed`:
// (A, B, C)
// (A, B, C, D, E)
// (A,) [E0277]
let foo = Foo { data: (1,) }; // ok
}