在Rust中实现通用的可增量特征

在Rust中实现通用的可增量特征

本文介绍了在Rust中实现通用的可增量特征的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图了解如何在Rust中实现通用特征.

I'm trying to understand how to implement a generic trait in Rust.

虽然我已经看到了许多示例,但是这些示例与特定用途相关联(例如),以便我能够在此时开始理解Rust的开发过程.

While I've seen a number of examples, the examples are too tied to a specific use (e.g. genomic mutators) for me to be able to understand at this point in my Rust development.

相反,这是一个基于相当通用的简单示例-递增:

Instead, here's a simple example based on something fairly universal--incrementing:

trait Incrementable {
    fn post_inc(&mut self) -> Self;
    fn post_inc_by(&mut self, n: usize) -> Self;
}

impl Incrementable for usize {
    fn post_inc(&mut self) -> Self {
        let tmp = *self;
        *self += 1;
        tmp
    }

    //"Overload" for full generalizability
    fn post_inc_by(&mut self, n: usize) -> Self {
        let tmp = *self;
        *self += n;
        tmp
    }
}

fn main() {
    let mut result = 0;
    assert!(result.post_inc() == 0);
    assert!(result == 1);

    assert!(result.post_inc_by(3) == 1);
    assert!(result == 4);
}

上面的代码有效,但是缺少它,因为没有编写很多样板代码就无法将其推广到所有数字类型.

The above code works, but is lacking because it isn't generalizable to all numeric types without writing a lot of boilerplate code.

在尝试推广上述代码时,我陷入了与类型系统的争执,借用检查器或被迫为我要在通用版本中支持的每种类型实现FromPrimitive的途径.我回到第一个方框).

In my attempts to generalize the above code, I've gotten into fights with the type system, borrow checker or been forced down a path of implementing FromPrimitive for every type I want to support in my generic version (effectively putting me back to square one).

您能帮我理解如何一般性地实现Incrementable的方法, 这样post_inc()post_inc_by()至少适用于所有整数和浮点类型,理想情况下不必为每种类型编写实现?

Can you help me understand how to implement Incrementable generically, such that post_inc() and post_inc_by() work for at least all integer and float types, ideally without having to write an implementation for each type?

我希望答案能够帮助我了解特质,实现,类型和关联类型如何在比我所遇到的更为直接的用例中协同工作.

I am hoping the answer will help me see how traits, implementations, types and associated types can work together in a more straightforward use case than I've been able to come across.

我使用的是Rust 1.16.0.

I'm on Rust 1.16.0.

推荐答案

您可以按照 std做了什么:

trait Incrementable {
    fn post_inc(&mut self) -> Self;
    fn post_inc_by(&mut self, n: Self) -> Self;
}

macro_rules! post_inc_impl {
    ($($t:ty)*) => ($(
        impl Incrementable for $t {
            fn post_inc(&mut self) -> Self {
                self.post_inc_by(1 as Self)
            }

            fn post_inc_by(&mut self, n: Self) -> Self {
                let tmp = *self;
                *self += n;
                tmp
            }
        }
    )*)
}

post_inc_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }

fn main() {
    let mut result = 0;
    assert!(result.post_inc() == 0);
    assert!(result == 1);

    assert!(result.post_inc_by(3) == 1);
    assert!(result == 4);
}

如果使用 num板条箱,则可能没有宏:

It is possible without macros if you use the num crate:

extern crate num;

use num::Num;

trait Incrementable<T: Num> {
    fn post_inc(&mut self) -> Self;
    fn post_inc_by(&mut self, n: T) -> Self;
}

impl<T: Num + std::ops::AddAssign<T> + Copy> Incrementable<T> for T {
    fn post_inc(&mut self) -> T {
        let tmp = *self;
        *self += T::one();
        tmp
    }

    fn post_inc_by(&mut self, n: T) -> Self {
        let tmp = *self;
        *self += n;
        tmp
    }
}

这篇关于在Rust中实现通用的可增量特征的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 02:58