What is the relationship between reference of tuple and tuple of reference as types?
Why does the first works but the second doesn't?
let a = 1;
let b = 2;
// This works, c: &i32, d:&i32
let (c, d) = &(a, b);
type TupleOfRef<'a> = (&'a i32, &'a i32);
let e = (a, b);
// This doesn't
let f: TupleOfRef = &e;
To make my point of question more clear. It is more about the relation of type (&'a A, &'a B)
with (A, B)
.
Thought the memory layout of tuple is not guaranteed, it is clear that can't make &(A, B)
out of &A
and &B
without cloning, since there is no one memory address holding A
and B
.
However, making (&A, &B)
out of (A, B)
makes some sense, since we have not only the address of tuple, (namely, &(A, B)
), but also at the addresses of its elements, (namely, &A
and &B
, as @etchesketch mentioned). And this seems work in the first case of the example above, but not in the second.
Actually the second is what I want. Is there anyway to (&A, &B, ..)
out of owned (A, B, ..)
in general? Or is there any good way to express these 'matchability' in trait bound?
Following question: Tuple of Reference and Reference of Tuple for type level operation
If you do that a lot, you can make it easier with a trait:
trait TupleOfRefs<'a> {
type Output: 'a;
fn as_tuple_of_refs (&'a self) -> Self::Output;
}
impl<'a, A: 'a> TupleOfRefs<'a> for (A,) {
type Output = (&'a A,);
fn as_tuple_of_refs (&'a self) -> Self::Output {
(&self.0,)
}
}
impl<'a, A: 'a, B: 'a> TupleOfRefs<'a> for (A, B) {
type Output = (&'a A, &'a B);
fn as_tuple_of_refs (&'a self) -> Self::Output {
(&self.0, &self.1)
}
}
fn main() {
let a = 1;
let b = 2;
let t = (a, b);
let r = t.as_tuple_of_refs();
println!("{r:?}");
}
The downside is that you first need to implement the trait for all possible tuple sizes (although it can be simplified with a macro):
macro_rules! make_tuple_of_refs {
($($t:ident $i:tt),*) => {
impl <'a, $($t: 'a),*> TupleOfRefs<'a> for ($($t,)*) {
type Output = ($(&'a $t,)*);
fn as_tuple_of_refs (&'a self) -> Self::Output {
($(&self.$i,)*)
}
}
}
}
trait TupleOfRefs<'a> {
type Output: 'a;
fn as_tuple_of_refs (&'a self) -> Self::Output;
}
make_tuple_of_refs!(A 0);
make_tuple_of_refs!(A 0, B 1);