function - 如何在Rust中命名关联函数的类型?

标签 function generics rust closures traits

我正在尝试编写对某个操作通用的代码,但对于常用的代码也具有便利功能,例如我想为所有类型T: Add定义的加法功能。
如果我定义独立函数,则可以正常工作,因为我可以在返回值中使用impl Trait来隐藏不透明类型。
但是,如果要在特征中定义此函数,则必须命名为<T as Add>::add的类型。我怎样才能做到这一点?

use std::ops::Add;

struct Operation<T, F>
where
    F: Fn(T, T) -> T,
{
    arg: T,
    f: F,
}

fn addition<T>(arg: T) -> Operation<T, impl Fn(T, T) -> T>
where
    T: Add<Output = T>,
{
    Operation { arg, f: T::add }
}

trait Addable<T>
where
    T: Add<Output = T>,
{
    fn addition(self) -> Operation<T, impl Fn(T, T) -> T>;
    //fn addition(self) -> Operation<T, ???>;
}
错误:
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
  --> src/main.rs:22:39
   |
22 |     fn addition(self) -> Operation<T, impl Fn(T, T) -> T>;
   |                                       ^^^^^^^^^^^^^^^^^^

最佳答案

trait方法的返回位置不允许使用impl Trait的原因是因为该方法可以有多种实现,而impl Trait仅在该函数或方法只有一个实现时才有效。
一种选择是使用盒装特征对象闭包:

trait Addable<T>
where
    T: Add<Output = T>,
{
    fn addition(self) -> Operation<T, Box<dyn Fn(T, T) -> T>>;
}
但是,由于闭包似乎不太可能需要从其环境中捕获变量,因此可以改用纯函数指针。这样可以节省不必要的堆分配。这是一个简单的i32示例,在trait方法的返回类型中使用了一个普通的函数指针:
trait Addable<T>
where
    T: Add<Output = T>,
{
    fn addition(self) -> Operation<T, fn(T, T) -> T>;
}

struct SomeType {
    arg: i32,
}

impl Addable<i32> for SomeType {
    fn addition(self) -> Operation<i32, fn(i32, i32) -> i32> {
        Operation {
            arg: self.arg,
            f: i32::add,
        }
    }
}
这是在trait方法返回类型中使用普通函数指针的通用示例:
trait Addable<T>
where
    T: Add<Output = T>,
{
    fn addition(self) -> Operation<T, fn(T, T) -> T>;
}

struct SomeType<T> {
    arg: T,
}

impl<T> Addable<T> for SomeType<T>
    where T: Add + Add<Output = T>
{
    fn addition(self) -> Operation<T, fn(T, T) -> T> {
        Operation {
            arg: self.arg,
            f: T::add,
        }
    }
}

关于function - 如何在Rust中命名关联函数的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66230787/

相关文章:

c - 此处有括号平衡的语义错误

java - 如何转换多个函数以创建通用函数

java - `Iterable` 的接口(interface)转换

rust - 将变量类型作为函数参数传递给rust?

c++ - 循环中的函数,参数不变

javascript - 使用另一个属性计算对象属性值

c - C语言如何将字符串从尾部复制到开头

Java 通用列表<List<?扩展号码>>

rust - Rust 泛型上的类型参数不匹配错误

rust - 在一个表达式中两次借用 self 有时会导致错误