Cannot explicitly specialize a generic function Cannot explicitly specialize a generic function swift swift

Cannot explicitly specialize a generic function


I also had this problem and I found a workaround for my case.

In this article the author has the same problem

https://www.iphonelife.com/blog/31369/swift-programming-101-generics-practical-guide

So the problem seems to be, that the compiler needs to infer the type of T somehow. But it isn't allowed to simply use generic< type >(params...).

Normally, the compiler can look for the type of T, by scanning the parameter types because this is where T is used in many cases.

In my case it was a little bit different, because the return type of my function was T. In your case it seems that you haven't used T at all in your function. I guess you just simplified the example code.

So I have the following function

func getProperty<T>( propertyID : String ) -> T

And in case of, for instance

getProperty<Int>("countProperty")

the compiler gives me the error:

Cannot explicitly specialize a generic function

So, to give the compiler another source of information to infer the type of T from, you have to explicitly declare the type of the variable the return value is saved in.

var value : Int = getProperty("countProperty")

This way the compiler knows that T has to be an integer.

So I think overall it simply means that if you specify a generic function you have to at least use T in your parameter types or as a return type.


Swift 5

Typically there are many ways to define generic functions. But they are based on condition that T must be used as a parameter, or as a return type.

extension UIViewController {    class func doSomething<T: UIView>() -> T {        return T()    }    class func doSomethingElse<T: UIView>(value: T) {        // Note: value is a instance of T    }    class func doLastThing<T: UIView>(value: T.Type) {        // Note: value is a MetaType of T    }}

After that, we must provide T when calling.

let result = UIViewController.doSomething() as UIImageView // Define `T` by casting, as UIImageViewlet result: UILabel = UIViewController.doSomething() // Define `T` with property type, as UILabelUIViewController.doSomethingElse(value: UIButton()) // Define `T` with parameter type, as UIButtonUIViewController.doLastThing(value: UITextView.self) // Define `T` with parameter type, as UITextView

Ref:

  1. http://austinzheng.com/2015/01/02/swift-generics-pt-1/
  2. https://dispatchswift.com/type-constraints-for-generics-in-swift-d6bf2f0dbbb2


The solution is taking the class type as parameter (like in Java)

To let compiler know what type he is dealing with pass the class as argument

extension UIViewController {    func navigate<ControllerType: UIViewController>(_ dump: ControllerType.Type, id: String, before: ((ControllerType) -> Void)?){        let controller = self.storyboard?.instantiateViewController(withIdentifier: id) as! ControllerType        before?(controller)        self.navigationController?.pushViewController(controller, animated: true)    }}

Call as:

self.navigate(UserDetailsViewController.self, id: "UserDetailsViewController", before: {        controller in        controller.user = self.notification.sender    })