Rust中类似于C++11的类型衰减

4
在C++11中,您可以将通用类型降解为值类型,去除参考/右值语义和cv限定符,例如:
decay<int>::type // type is `int`
decay<const int&>::type // type is `int`
decay<int&&>::type // type is `int`

在Rust中是否有已知机制可以实现相同的效果,即去除引用修饰符、生命周期和mut限定符?例如:

decay<u32>::type <--- type is `u32`
decay<&u32>::type <--- type is `u32`
decay<&mut u32>::type <--- type is `u32`
decay<&static u32>::type <--- type is `u32`

背景:我正在尝试编写一个宏,用于生成一个struct,该结构存储由宏匹配的一堆函数参数的值。例如,宏可能包含参数foo: i32, bar:&Vec<String>,生成的结构应为:

struct GeneratedStruct {
    foo: i32,
    bar: Vec<String>,
}

1
我认为在Rust中,这将直接由宏处理,而不是使用特征(尽管您可以自己创建特征)。请记住,Rust宏操作的是抽象语法树,而不是文本,因此您实际上可以在宏中解析参数。 - Matthieu M.
Deref可以将&T转换为T,但如果我没记错,就无法知道T本身是否是&。 - Josh Lee
@MatthieuM。我认为宏不能帮助,例如 type I32Ref = &'static i32; ...; decay!(I32Ref) 应该会产生 i32,但在词法层面上是不知道这一点的。 - kennytm
@kennytm:啊,确实在存在别名的情况下... - Matthieu M.
@kennytm:我有一个创建trait Decay { type Type; }的主意,然而...虽然它可以实现&'a T&'a mut T两者,但我不能只为T实现它,因为那会产生冲突。 - Matthieu M.
@MatthieuM。您可以使用特化来解决冲突,但是<T作为衰减>::Type将永远无法解决。 - kennytm
1个回答

5

根据Matthieu M.kennytm在评论中的建议,您可以定义一个trait并使用特化(截至Rust 1.15.0为不稳定功能)来实现此目的。

#![feature(specialization)]

use std::any::TypeId;

trait Decay {
    type Type;
}

impl<T> Decay for T {
    default type Type = T;
}

impl<'a, T> Decay for &'a T {
    type Type = <T as Decay>::Type;
}

impl<'a, T> Decay for &'a mut T {
    type Type = <T as Decay>::Type;
}

fn foo<T: 'static>() {
    println!("{:?}", TypeId::of::<T>());
}

fn bar<T>() where <T as Decay>::Type: 'static {
    println!("{:?}", TypeId::of::<<T as Decay>::Type>());
}

fn main() {
    foo::<<i32 as Decay>::Type>();
    foo::<<&i32 as Decay>::Type>();
    foo::<<&mut i32 as Decay>::Type>();
    foo::<<&&i32 as Decay>::Type>();

    bar::<i32>();
    bar::<&i32>();
    bar::<&mut i32>();
    bar::<&&i32>();
}

太棒了!我不知道专门化可以应用于关联类型(真的从来没有想过)。 - Matthieu M.
不错!这个可以完成任务。但我不想只使用不稳定的库。我会继续研究并看看是否能够使用仅稳定功能来完成此操作。 - Donald Whyte

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接