Reputation: 33428
I have a function like this:
func register<T: Routable>(_ action: Action, withCallback callback: @escaping (T?) -> Void) {
notificationCenter.addObserver(forName: actionMap[action], object: nil, queue: .main, using: { notification in
let routable = T(userInfo: notification.userInfo)
callback(routable)
})
}
Where Routable
is defined like:
protocol Routable {
init?(userInfo: [AnyHashable: Any]?)
}
When I try to use it, I receive
Cannot explicitly specialize a generic function
This is the usage:
controller.register<Navigate>(Action.navigate) { [unowned self] navigate in
// do something
}
Any idea to make the compiler happy?
Upvotes: 3
Views: 1141
Reputation: 299325
I believe this is purely a syntax issue. You can't pass the type parameter directly like this. You need to "fill in the type hole" instead. To do that, you need to add the type to navigate
:
controller.register(Action.navigate) { [unowned self] (navigate: Navigate?) in ... }
Sometimes that syntax is annoying because it buries the type. You can improve it by rewriting the signature of register
this way:
func register<T: Routable>(action: Action, returning: T.type,
withCallback callback: @escaping (T?) -> Void)
You'd then call it this way:
controller.register(action: .navigate, returning: Navigate.self) {
[unowned self] navigate in
// ...
}
The returning
parameter isn't directly used in the function. It just provides a more explicit way to specialize the function.
Upvotes: 5
Reputation: 23701
It's really hard to say without seeing a more complete code example... but basically what the compiler is telling you is "You told me you want the register function to be generic (because it has a type parameter) but then you are also trying to tell me exactly what type to use and I don't like that".
The point at which you are "explicitly specializ[ing]" the function is when you add a specific type parameter in the call:
controller.register<Navigate>...
# Right Here ^^^^^^^^^^
The compiler wants the flexibility to determine what type of register function to call. I suspect what you want is:
controller.register(Action.navigate) {...
Where you do not explicitly specialize the generic function but let the complier figure out which specialization to use.
Upvotes: 0