【发布时间】:2019-07-17 19:20:10
【问题描述】:
我不确定我的问题的标题是否正确,因为我不确定确切的位置。 假设我有一个看起来像这样的代码:
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 实现了 trait Fn。
但是,我应该尝试在 trait 中使用它吗?
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;
}
在这里,我抱怨说 Self 不能用作 Value。
我尝试通过在 trait 上引入条件 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)
}
}
感谢大家的回答!
【问题讨论】:
-
“说实话,我想要实现的就是实现这样的trait”请完成你想要的真实案例,目前距离minimal reproducible example
-
impl MyTrait for MyWrapper{};在语法上不正确:删除分号,您仍然会收到您声称的错误消息。 -
trait MyTrait where Self: ...通常应该写成trait MyTrait: ...。 -
@SvenMarnach 很有趣。我同意,但是当编译器给出提示时,它会在此处建议
where构造。
标签: rust