Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can i make same-type requirement in swift with generics? Is there any way?

Tags:

generics

swift

Ok so i have some class defined like this:

public final class Process<InputType, OutputType, Memory>

And i want to make the function available only for case when InputType and OutputType are exactly same type. So i tried like this like this:

extension Process where InputType == OutputType { }

But this would result in:

Same-type requirement makes generic parameters InputType and OutputType equivalent

So then i've gone a bit far and tried to do it like this:

func bypass<SameType>() -> Process<SameType, SameType, Memory> where OutputType == InputType {}

But this would result in exactly same error. So the question is why can't i define generics in such way that two generic types would be Equivalent, cause that's exactly what i wanted. I wanted to define function available only for this case, that would fail at compile time if this rule is not followed.

So right now i'm using something like this:

public static func bypass<SameType>() -> Process<SameType, SameType, Memory>

Which would ultimately fail only at runtime and not even when created but when the concrete class is triggered for action.

Is there any way to define extension or function for generic parameters of same type that would just not compile(result in compile time error)?

Update: some details of implementations are missed cause would make code unreadable and they are not critical for the context

like image 528
Igor Muzyka Avatar asked Dec 02 '16 22:12

Igor Muzyka


1 Answers

In Swift 4 and later, you can write:

public final class Process<InputType, OutputType, Memory> {
    // ...
}

extension Process where InputType == OutputType {
    func bypass() -> Process<InputType, OutputType, Memory> {
        // ...
    }
}

Original answer (Swift 3):

You can't constraint types on generic classes yet even though some changes are coming in Swift 4. However, you can constraint types on a protocol. You can make a protocol that only Process conforms to like this:

protocol ProcessProtocol {
    // I haven't found a way to name these associated type identically to
    // those in the class. If anyone discover a way, please let me know
    associatedtype IT
    associatedtype OT
    associatedtype MT
}

final public class Process<InputType, OutputType, MemoryType>: ProcessProtocol {
    typealias IT = InputType
    typealias OT = OutputType
    typealias MT = MemoryType

    // your code
}

// Note that this is an extension on the protocol, not the class
extension ProcessProtocol where IT == OT {
    func foo() {
        // this function is only available when InputType = OutputType
    }
}
like image 135
Code Different Avatar answered Mar 05 '23 13:03

Code Different