In Swift, I have a custom struct with this basic premise:
A wrapper struct that can contain any type that conforms to BinaryInteger
suc
Martin R's answer is a good solution. An alternative that doesn't require an extra marker protocol is this: write an unconstrained extension on Collection
, and in that extension, define a generic function that's constrained to where Element == SomeType<T>?
:
extension Collection {
func values<T>() -> [T?] where Element == SomeType<T>? {
return map( { $0?.value })
}
}
This works:
let arr: [SomeType<Int>?] = [SomeType(value: 123), SomeType(value: 456)]
arr.values() // [Optional(123), Optional(456)]
You'll notice that I used a func
instead of a computed property. I couldn't get the generic syntax right. Isn't this supposed to work?
extension Collection {
// error: consecutive declarations on a line must be separated by ';'
var values<T>: [T?] where Element == SomeType<T>? {
return self.map( { $0?.value })
}
}
I don't know if there is a simpler solution now, but you can use the same “trick” as in How can I write a function that will unwrap a generic property in swift assuming it is an optional type? and Creating an extension to filter nils from an Array in Swift, the idea goes back to this Apple Forum Thread.
First define a protocol to which all optionals conform:
protocol OptionalType {
associatedtype Wrapped
var asOptional: Wrapped? { get }
}
extension Optional : OptionalType {
var asOptional: Wrapped? {
return self
}
}
Now the desired extension can be defined as
extension Collection where Element: OptionalType, Element.Wrapped: SomeTypeProtocol {
var values: [Element.Wrapped.NumberType?] {
return self.map( { $0.asOptional?.value })
}
}
and that works as expected:
let arr = [SomeType(value: 123), nil, SomeType(value: 456)]
let v = arr.values
print(v) // [Optional(123), Optional(456)]
print(type(of: v)) // Array<Optional<Int>>