2017-03-05 18 views
2

我希望能夠通過給變異體構造一個值,構造枚舉值創建變體:不帶參數從空的元組

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的一個子集另一個。我認爲這是因爲第一個implfor T中的T比第二個實現中的for FF更通用。因此,它不可能是專業化的。

在另一方面,它不可能是一般的(default)實現,因爲Constructor<(), T> for T(甚至Constructor<S, T> for T)比Constructor<S, T> for F更具體,因爲T是在前兩次寫入。

這是我從閱讀RFC的理解。請告訴我,如果我錯了。

我怎樣才能使第一個例子工作,而不必給Unit一個無用的參數?

我很喜歡夜間編譯器的解決方案。

回答

1

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 (儘管第二個參數只能是())。