I have a class with a property that is a case from an Enum. I want to write a generic function to get the index of the case in the Enum's allCases
.
I begin by defining a protocol HasEnumCase
which simply states that adopters have an associated CaseIterable & Equatable
type.
protocol HasEnumCase {
associatedtype TheEnum: CaseIterable & Equatable
var theCase: TheEnum { get }
}
This does not compile.
func getIndexInAllCases<T: HasEnumCase>(theInstance: T) -> Int {
let allCases = T.TheEnum.allCases
let index = allCases.firstIndex(of: theInstance.theCase)
return index
}
//Cannot convert return expression of type 'T.TheEnum.AllCases.Index' to return type 'Int'
It compiles when I am using a concrete type.
enum MyEnum: CaseIterable {
case zero
case one
}
class HasEnumClass {
typealias E = MyEnum
var myEnum: MyEnum = .one
}
let h = HasEnumClass()
let caseIndex = type(of: h.myEnum).allCases.firstIndex(of: h.myEnum)
// caseIndex = 1
答案 0 :(得分:2)
The type Index
defined on Collection
doesn't have to be an Int
, which is why you're seeing the error. You can use generic constraints to require this, though:
func getIndexInAllCases<T: HasEnumCase>(theInstance: T) -> Int where T.TheEnum.AllCases.Index == Int {
// ...
}
答案 1 :(得分:0)
daltonclaybrook's reasoning and answer is correct: the issue is the type of Index
.
I found I can also create an array from the result of allCases
and the compiler will do the rest.
func getIndexInAllCases<T: HasEnumCase>(theInstance: T) -> Int {
let allCases = Array(type(of: theInstance).TheEnum.allCases)
let index = allCases.firstIndex(of: theInstance.theCase)!
return index
}