gpt4 book ai didi

rust - 从空元组创建不带参数的变体

转载 作者:行者123 更新时间:2023-11-29 08:00:59 25 4
gpt4 key购买 nike

我希望能够通过给变体构造函数一个值来构造枚举值:

use self::Variants::*;

#[derive(Clone, Debug)]
enum Variants {
Unit(()),
One(u8),
}

fn emit<C: Fn(S) -> T, S, T>(constructor: C, value: S) -> T {
constructor(value)
}

fn main() {
let unit: Variants = emit(&Unit, ());
println!("{:?}", unit); // Prints Unit(()).
let one: Variants = emit(&One, 10);
println!("{:?}", one); // Prints One(10).
}

这个例子的问题是我需要 ()Unit(())而不是更正常的 Unit (无参数)。

我尝试使用特化:

#![feature(specialization)]

trait Constructor<S, T> {
fn construct(self, value: S) -> T;
}

impl<T> Constructor<(), T> for T {
fn construct(self, _value: ()) -> T {
self
}
}

impl<F: Fn(S) -> T, S, T> Constructor<S, T> for F {
default fn construct(self, value: S) -> T {
self(value)
}
}

fn emit<C: Constructor<I, R>, I, R>(callback: &C, value: I) -> R {
callback.construct(value)
}

use self::Variants::*;

#[derive(Clone, Debug)]
enum Variants {
Unit,
One(u8),
}

fn main() {
let unit: Variants = emit(&Unit, ());
println!("{:?}", unit); // Should prints Unit.
let one: Variants = emit(&One, 10);
println!("{:?}", one); // Prints One(10).
}

但这在编译时失败了:

conflicting implementations of trait `Constructor<(), _>`:

根据我对 RFC 的理解, 这失败了,因为这些 impl 中没有一个s 是另一个的子集。我认为这是因为 Tfor T第一个 implF 更通用的 for F第二次实现。因此,它不能是特化。

另一方面,它不能是通用的 ( default ) 实现,因为 Constructor<(), T> for T (甚至 Constructor<S, T> for T )比 Constructor<S, T> for F 更具体因为T前者写了两次。

这是我阅读RFC 的理解。如果我错了请告诉我。

我怎样才能使第一个示例工作而不必给 Unit 一个无用的参数? ?

我对需要夜间编译器的解决方案持开放态度。

最佳答案

如何为 Variants 实现 Fn? (注意:Fn 需要 FnMutFnMut 需要 FnOnce,所以我们必须实现这三个。)

#![feature(fn_traits)]
#![feature(unboxed_closures)]

use self::Variants::*;

#[derive(Clone, Debug)]
enum Variants {
Unit,
One(u8),
}

impl FnOnce<((),)> for Variants {
type Output = Variants;

extern "rust-call" fn call_once(self, args: ((),)) -> Self::Output {
self.call(args)
}
}

impl FnMut<((),)> for Variants {
extern "rust-call" fn call_mut(&mut self, args: ((),)) -> Self::Output {
self.call(args)
}
}

impl Fn<((),)> for Variants {
extern "rust-call" fn call(&self, _: ((),)) -> Self::Output {
self.clone()
}
}

fn emit<C: Fn(S) -> T, S, T>(callback: &C, value: S) -> T {
callback(value)
}

fn main() {
let unit: Variants = emit(&Unit, ());
println!("{:?}", unit); // Prints Unit.
let one: Variants = emit(&One, 10);
println!("{:?}", one); // Prints One(10).
}

此解决方案唯一奇怪的方面是您现在可以将 &One(10) 等值作为第一个参数传递给 emit(尽管第二个参数只能是 ()).

关于rust - 从空元组创建不带参数的变体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42614589/

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