gpt4 book ai didi

rust - 如何给 impl 特征起别名?

转载 作者:行者123 更新时间:2023-11-29 08:05:46 27 4
gpt4 key购买 nike

我有以下类型签名的许多功能:

fn f() -> impl Fn(u32) -> u32 { 
|x: u32| x
}

如何为 Fn(u32) -> u32 命名,这样我就不必重复了?尽管我可以执行 type X = Fn(u32) -> u32;,但 Rust 不允许我使用它,因为它是一种类型而不是特征。我必须等待 trait_alias或者我可以做点别的吗?

最佳答案

你完全正确。 impl X 要求 X 成为特征,并且在 trait aliases 之前不可能拥有适当的特征别名土地。当发生这种情况时,您将能够执行此操作:

#![feature(trait_alias)]

trait X = Fn(u32) -> u32;

fn f() -> impl X {
|x: u32| x
}

(playground)


或者,当 Permit impl Trait in type aliases土地,你将能够使 impl trait 成为 type 别名。不过,这略有不同。当我们使用 type X = impl Trait 进行别名时,编译器将确保 X 的每次使用实际上都是相同的具体类型。这意味着,在您的情况下,您将无法将它与多个不同的闭包一起使用,因为每个闭包都有自己独特的类型。

#![feature(type_alias_impl_trait)]

type X = impl Fn(u32) -> u32;

fn f() -> X {
|x: u32| x
}

(playground)

但是,这不会编译

#![feature(type_alias_impl_trait)]

type X = impl Fn(u32) -> u32;

fn f() -> X {
|x: u32| x
}

// Even a closure with exactly the same form has a different type.
fn g() -> X {
|x: u32| x
}

错误是

error: concrete type differs from previous defining opaque type use
--> src/lib.rs:10:1
|
10 | / fn g() -> X {
11 | | |x: u32| x
12 | | }
| |_^ expected `[closure@src/lib.rs:7:5: 7:15]`, got `[closure@src/lib.rs:11:5: 11:15]`
|
note: previous use here
--> src/lib.rs:6:1
|
6 | / fn f() -> X {
7 | | |x: u32| x
8 | | }
| |_^

(playground)

这与特征别名形成对比,特征别名允许将不同的具体类型用于每个返回 impl TraitAlias 的函数。请参阅介绍 this syntax 的 RFC和 existential types in general了解更多。


在这两个功能中的一个出现之前,您可以获得与 trait 别名类似的行为,本质上是一种 hack。这个想法是创建一个新的特征,它在本质上等同于原始特征,但名称更短。

// This trait is local to this crate,
// so we can implement it on any type we want.
trait ShortName: Fn(u32) -> u32 {}

// So let's go ahead and implement `ShortName`
// on any type that implements `Fn(u32) -> u32`.
impl<T: Fn(u32) -> u32> ShortName for T {}

// We can use `ShortName` to alias `Fn(u32) -> u32`.
fn f() -> impl ShortName {
|x: u32| x
}

// Moreover, the result of that can be used in places
// that expect `Fn(u32) -> u32`.
fn g<T: Fn(u32) -> u32>(x: &T) -> u32 {
x(6_u32)
}

fn main() {
// We only know that `x` implements `ShortName`,
let x = f();
// But we can still use `x` in `g`,
// which expects an `Fn(u32) -> u32` argument
let _ = g(&x);
}

(playground)

关于rust - 如何给 impl 特征起别名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57937436/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com