swiftgenerics

Swift default implementation initializer for protocol through extension


I am trying to add an initializer to a struct that will default to a default implementation of a protocol if one isn't provided.

protocol MyProtocol {
    associatedtype Element
    
    var value: Element { get set }
}
struct MyStruct<T: MyProtocol> {
    var member: T
  
    init(member: T) {
        self.member = member
    }
}
struct DefaultProtocolImplementation<ImplType>: MyProtocol {
    var value: ImplType
}

I add an initializer through an extension, like so:

extension MyStruct {
    init(value: T.Element) {
        self.member = DefaultProtocolImplementation(value: value)
    }
}

but this gives me "Cannot assign value of type 'DefaultProtocolImplementation<T.Element>' to type 'T'"

If I try to constrain the type like this:

extension MyStruct where T == DefaultProtocolImplementation<T.Element> {
    init(value: T.Element) {
        self.member = DefaultProtocolImplementation(value: value)
    }
}

Then I get "Same-type constraint 'T' == 'DefaultProtocolImplementation<T.Element>' is recursive"

Is there a way I can achieve this default implementation constructor?


Solution

  • You can break the recursion by introducing a new type parameter,

    extension MyStruct {
        init<Element>(value: Element) where T == DefaultProtocolImplementation<Element> {
            self.member = DefaultProtocolImplementation(value: value)
        }
    }