“impl”用作函数的参数类型或返回类型时意味着什么?

问题描述 投票:0回答:2

我读了这段代码

pub fn up_to(limit: u64) -> impl Generator<Yield = u64, Return = u64> {
    move || {
        for x in 0..limit {
             yield x;
        }
        return limit;
    }
}

impl
是什么意思?这如何用普通的 Rust 或 C++ 实现?

rust
2个回答
25
投票

这是新的

impl Trait
语法,它允许程序员避免命名泛型类型。该功能从 Rust 1.26 开始可用。

在这里,它用在返回位置中,表示“返回的类型将实现这个特征,这就是我要告诉你的”。在这种情况下,请注意函数的所有返回路径必须返回完全相同的具体类型。

该语法也可以用在参数位置,在这种情况下,调用者决定传递什么具体类型。

另请参阅:


6
投票

impl
是什么意思?

正如 Matthieu 所解释的,

impl X
的意思是“返回特质
X
的具体实现”。如果没有这个,您可以选择返回实现该特征的具体类型,例如
UpToImpl
,或通过返回
Box<Generator>
来擦除类型。前者需要公开类型,而后者则需要动态分配和虚拟调度的运行时成本。更重要的是,这是生成器情况的关键,前一种方法阻止返回闭包,因为闭包返回匿名类型的值。

这如何用普通 Rust 或 C++ 实现?

如果您的意思是如何实现

up_to
,并且希望在不产生分配开销的情况下实现它,则必须放弃使用闭包并手动将生成器重写为实现
Generator
特征的状态机:

#![feature(generator_trait)]
use std::{
    ops::{Generator, GeneratorState},
    pin::Pin,
};

pub struct UpToImpl {
    limit: u64,
    x: u64,
}

impl Generator for UpToImpl {
    type Yield = u64;
    type Return = u64;

    fn resume(mut self: Pin<&mut Self>) -> GeneratorState<u64, u64> {
        let x = self.x;
        if x < self.limit {
            self.x += 1;
            GeneratorState::Yielded(x)
        } else {
            GeneratorState::Complete(self.limit)
        }
    }
}

pub fn up_to(limit: u64) -> UpToImpl {
    UpToImpl { x: 0, limit }
}

fn main() {
    let mut v = Box::pin(up_to(3));
    println!("{:?}", v.as_mut().resume());
    println!("{:?}", v.as_mut().resume());
    println!("{:?}", v.as_mut().resume());
    println!("{:?}", v.as_mut().resume());
}

这种转换本质上是 Rust 编译器在给定包含

yield
的闭包时在幕后执行的操作,只不过与
UpToImpl
等效的生成类型是匿名的。 (类似但更简单的转换用于将普通闭包转换为实现
Fn
特征之一的匿名类型的值。)

返回

impl Generator
和具体类型之间还有另一个区别。当返回
UpToImpl
时,该类型必须是公共的,因此成为函数签名的一部分。例如,允许调用者执行以下操作:

let x: UpToImpl = up_to(10);

如果

UpToImpl
被重命名,或者如果您决定切换到使用生成器闭包,该代码将会中断。

这个答案中的

up_to
即使更改为返回
impl Generator
也会编译,因此它是实现最大灵活性的更好选择。当
impl Generator
返回时,调用者不能依赖或引用具体的返回类型。返回类型可以切换到实现该特征的any类型,包括匿名闭包,而不会损失向后兼容性。

另请参阅:

© www.soinside.com 2019 - 2024. All rights reserved.