Moshe Gottlieb
Moshe Gottlieb

Reputation: 4013

Explicitly specialize a generic function is swift

I'm trying to call a static method on a swift class using a generic function, so I don't really need the type of the class to be a part of the function signature.
Can't seem to find a way to do it.

Here's a C++ sample of what I'm trying to do:

#include <iostream>

class A {
public:
    static void f(){
        std::cout << "A::f()" << std::endl;
    }
};

class B {
public:
    static void f(){
        std::cout << "B::f()" << std::endl;
    }
};

template <typename T>
void callF(){
    T::f();
}

int main(){
    callF<A>();
    callF<B>();
    return 0;
}

Here I use explicit specialization for callF with the type I need.
I realize swift's generics are not templates, and I can't just call anything I want and let the compiler break if it's not valid, so I added a protocol and made the generic parameter require conformance to the protocol (P in the following example) but I can't seem to find a way to tell the compiler I want to use a certain type without including it in the function's signature.
This is the cleanest method I came up with:

protocol P{
    static func f();
}

class A : P {
    static func f(){
        print("A.f()")
    }
}

class B : P {
    static func f(){
        print("B.f()")
    }
}

func callF<T:P>() -> T? {
    T.f()
    return nil
}

let _:A? = callF()
let _:B? = callF()

I really don't like using dummies in my code, but I can't work around this.
Any thoughts on how to avoid using dummies in the function signature and have swift figure out which type I want to use? I obviously tried callF<A>() and got: error: cannot explicitly specialize a generic function

Upvotes: 0

Views: 727

Answers (1)

David Pasztor
David Pasztor

Reputation: 54745

You should pass the type that you want f() to be called on into the callF function as an input argument.

func callF<T:P>(on type:T.Type) {
    type.f()
}

callF(on: A.self) // A.f()
callF(on: B.self) // B.f()

Upvotes: 2

Related Questions