Rust 有没有一种简单的方法可以一次性转换整个标量值元组?

Rust 有没有一种简单的方法可以一次性转换整个标量值元组?,rust,Rust,我想将(u16,u16)转换为(f32,f32)。这就是我所尝试的: let tuple1 = (5u16, 8u16); let tuple2 = tuple1 as (f32, f32); 理想情况下,我希望避免写作 let tuple2 = (tuple1.0 as f32, tuple1.1 as f32); 不,, 那里 是 不可以。不,你不能。这大致相当于“我可以一次将结构中的所有字段强制转换为不同的类型吗?” 你可以编写一个通用的扩展特性来完成这个转换,唯一的问题是我不相信有任

我想将
(u16,u16)
转换为
(f32,f32)
。这就是我所尝试的:

let tuple1 = (5u16, 8u16);
let tuple2 = tuple1 as (f32, f32);
理想情况下,我希望避免写作

let tuple2 = (tuple1.0 as f32, tuple1.1 as f32);
不,, 那里 是
不可以。

不,你不能。这大致相当于“我可以一次将结构中的所有字段强制转换为不同的类型吗?”

你可以编写一个通用的扩展特性来完成这个转换,唯一的问题是我不相信有任何现有的通用“转换”特性也定义了一个
u16->f32
实现

如果你真的想要一个能做到这一点的函数,这里有一个尽可能少的框架,你可以在此基础上构建:

trait TupleCast<T> {
    type Output;
    fn tuple_cast(self) -> <Self as TupleCast<T>>::Output;
}

impl<T> TupleCast<T> for () {
    type Output = ();
    fn tuple_cast(self) -> <() as TupleCast<T>>::Output {
        ()
    }
}

impl<S, T> TupleCast<T> for (S,) where S: CustomAs<T> {
    type Output = (T,);
    fn tuple_cast(self) -> <(S,) as TupleCast<T>>::Output {
        (self.0.custom_as(),)
    }
}

impl<S, T> TupleCast<T> for (S, S) where S: CustomAs<T> {
    type Output = (T, T);
    fn tuple_cast(self) -> <(S, S) as TupleCast<T>>::Output {
        (self.0.custom_as(), self.1.custom_as())
    }
}

// You would probably have more impls, up to some size limit.

// We can't use std::convert::From, because it isn't defined for the same
// basic types as the `as` operator is... which kinda sucks.  So, we have
// to implement the desired conversions ourselves.
//
// Since this would be hideously tedious, we can use a macro to speed things
// up a little.

trait CustomAs<T> {
    fn custom_as(self) -> T;
}

macro_rules! custom_as_impl {
    ($src:ty:) => {};
    ($src:ty: $dst:ty) => {
        impl CustomAs<$dst> for $src {
            fn custom_as(self) -> $dst {
                self as $dst
            }
        }
    };
    ($src:ty: $dst:ty, $($rest:ty),*) => {
        custom_as_impl! { $src: $dst }
        custom_as_impl! { $src: $($rest),* }
    };
}

// You could obviously list others, or do manual impls.
custom_as_impl! { u16: u16, u32, u64, i32, i64, f32, f64 }

fn main() {
    let x: (u16, u16) = (1, 2);
    let y: (f32, f32) = x.tuple_cast();
    println!("{:?}", y);
}
trait-TupleCast{
类型输出;
fn tuple_cast(self)->:输出;
}
为(){
类型输出=();
fn元组_cast(self)->:输出{
()
}
}
(S,)的impl TupleCast,其中S:CustomAs{
类型输出=(T,);
fn元组_cast(self)->:输出{
(self.0.custom_as(),)
}
}
(S,S)的impl TupleCast,其中S:CustomAs{
类型输出=(T,T);
fn元组_cast(self)->:输出{
(self.0.custom_as(),self.1.custom_as())
}
}
//您可能会有更多的impl,达到一定的大小限制。
//我们不能使用std::convert::From,因为它不是为同一个对象定义的
//基本类型作为'as'运算符是。。。这有点糟糕。所以,我们有
//我们自己实现所需的转换。
//
//由于这将是可怕的乏味,我们可以使用宏来加速事情
//往上一点。
特质习惯{
fn自定义_as(self)->T;
}
宏规则!按要求定制{
($src:ty:)=>{};
($src:ty:$dst:ty)=>{
$src的impl CustomAs{
fn自定义设置(自身)->$dst{
self as$dst
}
}
};
($src:ty:$dst:ty,$($rest:ty),*)=>{
自定义_as_impl!{$src:$dst}
自定义\u作为\u impl!{$src:$($rest),*}
};
}
//很明显,您可以列出其他人,或者手动执行impl。
按需定制!{u16:u16,u32,u64,i32,i64,f32,f64}
fn main(){
设x:(u16,u16)=(1,2);
设y:(f32,f32)=x.tuple_cast();
println!(“{:?}”,y);
}

没有内置的方法,但可以使用宏:

macro_rules! tuple_as {
    ($t: expr, ($($ty: ident),*)) => {
        {
            let ($($ty,)*) = $t;
            ($($ty as $ty,)*) 
        }
    }
}

fn main() {
    let t: (u8, char, isize) = (97, 'a', -1);

    let other = tuple_as!(t, (char, i32, i8));

    println!("{:?}", other);
}
打印
('a',97,-1)


宏仅适用于名称为单个标识符的类型之间的强制转换(这就是
:ident
所指的),因为它重用这些名称绑定到源元组的元素,以便能够强制转换它们。所有基元类型都是有效的单一标识符,因此对这些基元类型都很有效。

在我看来,这是一种很棒的方法,谢谢!我还没有太多地使用宏,所以我不知道这样的事情是可能的。