我希望能够通过为变量构造函数赋值:
来构造枚举值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
中没有一个是另一个的子集。我认为这是因为第一个T
的{{1}}中的for T
比第二个实现的impl
的{{1}}更通用。因此,它不能是专业化。
另一方面,它不能是一般的(F
)实现,因为for F
(甚至default
)比Constructor<(), T> for T
更具体,因为{{1}在前者写了两次。
这是我阅读RFC的理解。请告诉我,如果我错了。
如何在不向Constructor<S, T> for T
提供无用参数的情况下使第一个示例正常工作?
我对需要夜间编译器的解决方案持开放态度。
答案 0 :(得分:1)
为Fn
实施Variants
怎么样? (注意:Fn
需要FnMut
而FnMut
需要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
(尽管第二个参数只能是()
)。 / p>