我正在尝试编写对某个操作通用的代码,但对于常用的代码也具有便利功能,例如我想为所有类型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/