2017-08-09 166 views
-1

我想實現的東西給這個效果:返回通用枚舉

enum Foo: Int { case a, b, c, d } 
enum Bar: Int { case a, b, c, d } 

func generate<T: RawRepresentable>(using index: Int) -> T 
{ 
    guard let output = T(rawValue: index) else { preconditionFailure() } 
    return output 
} 

但我得到的錯誤:

Playground execution failed: error: GenericEnums.playground:18:24: error: cannot invoke initializer for type 'T' with an argument list of type '(rawValue: Int)' 
    guard let output = T(rawValue: index) else { preconditionFailure() } 
        ^

GenericEnums.playground:18:24: note: expected an argument list of type '(rawValue: Self.RawValue)' 
    guard let output = T(rawValue: index) else { preconditionFailure() } 

我要去哪裏錯了?

+0

「爲此」不解釋足夠精確你正在嘗試做的。 – matt

回答

3

首先,index不應該Int,但它應該是T.RawValue,因爲RawRepresentable協議不指定RawValue的類型是Int。其次,如果您不想鍵入註釋將generate返回值賦給的變量,則應將泛型類型參數T應用於表示要生成的類型的輸入參數。

以下是您的通用函數的工作和測試實現。 value參數需要是您想要生成的enum的類型。

enum Foo: Int { case a, b, c, d } 
enum Bar: Int { case a, b, c, d } 

func generate<T: RawRepresentable>(value ofClass: T.Type,using index: T.RawValue) -> T { 
    guard let output = T(rawValue: index) else { preconditionFailure() } 
    return output 
} 

//the output of this version needs to be assigned to a type annotated variable, 
//otherwise the compiler cannot figure out the exact type that T represents 
func generate<T: RawRepresentable>(using index: T.RawValue) -> T { 
    guard let output = T(rawValue: index) else { preconditionFailure() } 
    return output 
} 

generate(value:Foo.self, using: 1) //returns Foo.b 
let a: Bar = generate(using: 0) //returns Bar.a 
+1

「否則編譯器會知道,T代表什麼類型?」它可以通過查看賦予'generate'結果的變量的類型來知道。 – matt

+0

感謝@matt的輸入,甚至沒有意識到這是可能的。用另一個版本的函數更新了我的答案。 –

2

DávidPásztor的答案是更通用的答案,應該在大多數情況下使用。

但是,如果你想要做的專門只有Int基於RawRepresentable類型的東西,你 可以這樣做:

func generate<T: RawRepresentable>(using index: Int) -> T where T.RawValue == Int 
{ 
    guard let output = T(rawValue: index) else { preconditionFailure() } 
    return output 
} 
0

個人而言,我覺得你的方式過這個思維。如果目標是當提供錯誤的原始值崩潰,做這樣的事情:

extension RawRepresentable { 
    init(rawValueOrDie what:RawValue) { 
     self.init(rawValue:what)! 
    } 
} 
+0

實際使用涉及傳遞爲給定枚舉生成索引的對象。每種類型的枚舉都有一個獨立的生成器,所以我想只寫一次generate方法。 – XmasRights

+0

那麼,正如我所說,你的問題並沒有解釋什麼是實際使用/目標_is_。 – matt