からパラメータなしの変異体を作成します。私はバリアントのコンストラクタに値を与えることによって、列挙値を構築することができるようにしたい空のタプル
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).
}
が、これはとコンパイル時に失敗します。これらの
impl
秒の誰もサブセットではありませんので、
RFCの私の理解から
conflicting implementations of trait `Constructor<(), _>`:
、これが失敗もう一方の第1のimpl
のfor T
のT
が第2の実施のfor F
のF
より一般的であるからであると私は考える。したがって、それは専門化することはできません。一方
T
が前者に二回書き込まれるためConstructor<(), T> for T
(さらにConstructor<S, T> for T
)がConstructor<S, T> for F
より特異的であるので、一般的な(default
)実装することができません。
これはRFCを読んだことから私の理解です。私が間違っているかどうか教えてください。
Unit
に無用なパラメータを指定しなくても、最初の例の動作をどうすればできますか?
ナイトリーコンパイラを必要とするソリューションにはオープンしています。