我不确定问题的标题是否正确,因为我不确定确切的位置。 假设我有一个看起来像这样的代码:
struct MyWrapper(u64);
fn my_func<F>(f: F, n: u64) -> MyWrapper
where
F: Fn(u64) -> MyWrapper,
{
f(n)
}
fn main() {
my_func(MyWrapper, 3);
}
它可以编译和运行,因此看起来MyWrapper
实现了特征Fn
。
但是,我应该尝试在特征中使用它吗。
struct MyWrapper(u64);
trait MyTrait
where
Self: Fn(u64) -> MyWrapper,
{
}
impl MyTrait for MyWrapper{}
我收到错误
16 | impl MyTrait for MyWrapper{};
| ^^^^^^^ expected an `Fn<(u64,)>` closure, found `MyWrapper`
|
= help: the trait `std::ops::Fn<(u64,)>` is not implemented for `MyWrapper`
这是一个更具理论性的问题。
实际上,我想要实现的是实现这样的特质
编辑: 我正确地指出,我的示例还不完整,因此有一个固定版本。
pub enum Status {
New,
Cancelled,
}
struct NewTransaction(u64);
struct CancelledTransaction(u64);
fn get_by_status(id: &str, status: Status) -> Result<u64, ()> {
Ok(3)
}
pub trait Transaction
where
Self: std::marker::Sized,
{
const status: Status;
fn get(id: &str) -> Result<Self, ()>;
}
impl Transaction for NewTransaction {
const status: Status = Status::New;
fn get(id: &str) -> Result<Self, ()> {
get_by_status(id, Self::status).map(Self)
}
}
impl Transaction for CancelledTransaction {
const status: Status = Status::Cancelled;
fn get(id: &str) -> Result<Self, ()> {
get_by_status(id, Self::status).map(Self)
}
}
该代码可以编译,但是如您所见-每种类型的Transaction的所有实现都是完全相同,因此将这种实现默认移动是完全合理的。像这样
pub trait Transaction
where
Self: std::marker::Sized,
{
const status: Status;
fn get(id: &str) -> Result<Self, ()> {
get_by_status(id, Self::status).map(Self)
}
}
impl Transaction for NewTransaction {
const status: Status = Status::New;
}
impl Transaction for CancelledTransaction {
const status: Status = Status::Cancelled;
}
在这里,我抱怨自己不能用作价值。
我已经尝试通过在特征上引入条件where Self: Fn(u32) -> Self
来解决此问题,但是它也不起作用。
编辑:
最后,我实现了Sven Marnach提出的想法-添加了方法new
并需要所有结构来实现此方法。看起来仍然很奇怪,因为所有结构的实现都是完全相同的,但是可以。
pub trait Transaction
where
Self: std::marker::Sized,
{
const status: Status;
fn new(n: u64) -> Self;
fn get(id: &str) -> Result<Self, ()> {
get_by_status(id, Self::status).map(Self::new)
}
}
impl Transaction for NewTransaction {
const status: Status = Status::New;
fn new(n: u64) -> Self {
Self(n)
}
}
感谢大家的回答!
答案 0 :(得分:5)
类似元组的struct或enum变体的构造函数在需要值而不是类型的上下文中使用时,实际上被视为函数名称。 em> type 它在需要类型的上下文中命名。
调用my_func(MyWrapper, 3)
时,名称MyWrapper
表示一个函数,该函数的功能项类型强制为函数指针类型fn(u64) -> MyWrapper
。特别是,项目类型实现特征Fn(u64) -> MyWrapper
。
但是,在代码impl MyTrait for MyWrapper{}
中,MyWrapper
表示您声明的结构类型。在值上下文中使用时,该类型与MyWrapper
的类型完全不同,并且不实现Fn(u64) -> MyWrapper
特质。
在您的实际用例中,我认为最简单的解决方案是要求使用new()
方法并在类型上具有所需的原型:
trait Payment {
const status: Status;
fn new(x: WhateverTypeGetByStatusReturns) -> Self;
fn get(id: u64) -> Result<Self, Error> {
get_by_status(Self::status, id).map(Self)
}
}
Payment
的实现者将只需要为new()
方法提供所需的原型,但将继承get()
的默认实现。
答案 1 :(得分:2)
它可以编译和运行,因此看起来像
MyWrapper
实现了特征Fn
。
一种快速而又肮脏的方法来了解Rust中某种事物的类型:
struct MyWrapper(u64);
fn main() {
let mut foo = MyWrapper;
foo = ();
}
这会产生错误:
error[E0308]: mismatched types
--> src/main.rs:5:11
|
5 | foo = ();
| ^^ expected fn item, found ()
|
= note: expected type `fn(u64) -> MyWrapper {MyWrapper}`
found type `()`
您可以看到foo
是{strong>不是一个MyWrapper
结构,因此MyWrapper
并没有像您想象的那样实现Fn
。>
我同意这可能会造成混淆,请参阅tuple struct case
:
带有用括号括起来的字段的结构表达式构造一个元组结构。尽管此处列出它是出于完整性的特定表达式,但它等效于元组结构的构造函数的call expression。例如:
struct Position(i32, i32, i32);
Position(0, 0, 0); // Typical way of creating a tuple struct.
let c = Position; // `c` is a function that takes 3 arguments.
let pos = c(8, 6, 7); // Creates a `Position` value.
实际上,我想要实现的是实现这样的特征
您的示例还不完整,所以我的回答不是最终的,但我认为不可能做您想做的事。