struct - 为 Rust 新类型自动实现封闭类型的特征(具有一个字段的元组结构)

标签 struct traits rust newtype

在 Rust 中,只有一个字段的元组结构可以像下面这样创建:

struct Centimeters(i32);

我想用厘米做基本的算术运算,而不是每次都用模式匹配提取它们的“内部”值,也不想实现AddSub, ... 特征和重载运算符。

我想做的是:

let a = Centimeters(100);
let b = Centimeters(200);
assert_eq!(a + a, b);

最佳答案

is there a way to do it without extracting their "inner" values every time with pattern matching, and without implementing the Add, Sub, ... traits and overloading operators?

不,唯一的方法是手动实现特征。 Rust 没有等同于 the Haskell's GHC extension GeneralizedNewtypeDeriving 的东西这允许 deriving 包装类型自动实现包装类型实现的任何类型类/特征(以及 Rust 的 #[derive] 的当前设置作为一个简单的AST 转换,像 Haskell 那样实现它本质上是不可能的。)

要简化流程,您可以使用宏:

use std::ops::{Add, Sub};

macro_rules! obvious_impl {
    (impl $trait_: ident for $type_: ident { fn $method: ident }) => {
        impl $trait_<$type_> for $type_ {
            type Output = $type_;

            fn $method(self, $type_(b): $type_) -> $type_ {
                let $type_(a) = self;
                $type_(a.$method(&b))
            }
        }
    }
}

#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Debug)]
pub struct Centimeters(i32);

obvious_impl! { impl Add for Centimeters { fn add } }
obvious_impl! { impl Sub for Centimeters { fn sub } }

#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Debug)]
pub struct Inches(i32);

obvious_impl! { impl Add for Inches { fn add } }
obvious_impl! { impl Sub for Inches { fn sub } }

fn main() {
    let a = Centimeters(100);
    let b = Centimeters(200);
    let c = Inches(10);
    let d = Inches(20);
    println!("{:?} {:?}", a + b, c + d); // Centimeters(300) Inches(30)
    // error:
    // a + c;
}

playpen

我在宏中模拟了普通的 impl 语法,仅通过查看宏调用(即减少查看宏定义的需要)就可以清楚地了解正在发生的事情,并维护Rust 的自然可搜索性:如果您正在寻找关于 Cenimeters 的特征,只需 grep for for Cenimeters,您会发现这些宏调用以及正常的 impls.

如果您经常访问 Centimeters 类型的内容,您可以考虑使用带有字段的适当结构来定义包装器:

struct Centimeters { amt: i32 }

这允许您编写 self.amt 而不必进行模式匹配。您还可以定义一个函数,如 fn cm(x: i32) -> Centimeters { Centimeters { amt: x } },调用方式如 cm(100),以避免构建完整结构的冗长。

您还可以使用 .0, .1 语法访问元组结构的内部值。

关于struct - 为 Rust 新类型自动实现封闭类型的特征(具有一个字段的元组结构),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40568179/

相关文章:

c - 未显示 c 中结构数组的正确值

Scala trait 及其方法的参数化

PHP:如何从当前类中使用的特征方法调用父方法?

rust - 在 rust 中使用 u32 整数类型

rust - 我应该按值还是按引用传递函数对象?

nested - 将具有父 ID 的结构列表转换为树列表

c - 基本问题 : C function to return pointer to malloc'ed struct

c# - 从 C 函数返回结构,C# 中的等价物是什么?

c - 树莓派上的结构段错误gcc

rust - 有没有办法将随机数生成器存储为特征对象?