gpt4 book ai didi

rust - 类型构造函数是否实现 Fn?

转载 作者:行者123 更新时间:2023-11-29 07:50:04 25 4
gpt4 key购买 nike

我不确定问题的标题是否正确,因为我不确定确切的位置。假设我有一个看起来像这样的代码:


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;
}

在这里我收到一个提示,说 Self 不能用作一个值。我试图通过引入条件 where Self: Fn(u32) -> Self on trait 来修复它,但它也没有用。

编辑:最后,我实现了 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)
}
}

谢谢大家的回答!

最佳答案

在期望值而不是类型的上下文中使用时,类元组结构或枚举变体的构造函数实际上被视为函数名,并且它被视为< em>type 它在需要类型的上下文中命名。

当调用 my_func(MyWrapper, 3) 时,名称 MyWrapper 表示一个函数,其函数项类型强制转换为函数指针类型 fn(u64 ) -> MyWrapper。特别是,项目类型实现了 Fn(u64) -> MyWrapper 特征。

但是,在代码 impl MyTrait for MyWrapper {} 中,MyWrapper 表示它声明的结构类型。当在值上下文中使用时,该类型与 MyWrapper 的类型完全不同,并且它不实现 Fn(u64) -> MyWrapper 特征。

在您的实际用例中,我认为最简单的解决方案是要求 new() 方法在类型上具有所需的原型(prototype):

trait Payment {
const status: Status;
fn new(x: u64) -> Self;
fn get(id: u64) -> Result<Self, Error> {
get_by_status(Self::status, id).map(Self::new)
}
}

Payment 的实现者只需要提供具有所需原型(prototype)的new() 方法,但会继承get() 的默认实现>.

关于rust - 类型构造函数是否实现 Fn?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57082823/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com