Swift generics: requiring addition and multiplication abilities of a type

前端 未结 2 1227
不思量自难忘°
不思量自难忘° 2020-12-05 07:57

I\'m trying out some examples from the Swift book, namely the matrix example they have which introduces subscript options. This is the code I have:

struct Ma         


        
相关标签:
2条回答
  • 2020-12-05 08:40

    Here's for your second question (but you really should ask two separate questions):

    @infix func + <T> (m1: Matrix<T>, m2: Matrix<T>) -> Matrix<T> { ... }
    

    For your first question: before solving it, here's the syntax to define multiple constraints for type parameter:

    struct Matrix<T where T: Equatable, T: Summable, T: Multipliable> {...}
    

    or, as GoZoner writes in the comments:

    struct Matrix<T: protocol<Equatable, Summable, Multipliable>> {...}
    

    But we're not going to need it. First, define a new protocol and list the operations that you need. You can even make it extend Equatable:

    protocol SummableMultipliable: Equatable {
        func +(lhs: Self, rhs: Self) -> Self
        func *(lhs: Self, rhs: Self) -> Self
    }
    

    Then, provide extensions for the types that you want to conform. Here, for Int and Double, the extensions are even empty, as the implementation of the needed ops is built-in:

    extension Int: SummableMultipliable {}
    extension Double: SummableMultipliable {}
    

    Then, declare your type constraint on the type parameter:

    struct Matrix<T: SummableMultipliable> { ... }
    

    Finally, you can write stuff like this:

    let intMat = Matrix<Int>(rows: 3, columns: 3, initialValue: 0)
    let doubleMat = Matrix<Double>(rows: 3, columns: 3, initialValue: 0)
    let i: Int = intMat[0,0]
    let d: Double = doubleMat[0,0]
    

    The last thing you'll need is to insert the type constraint in the definition of your operator:

    @infix func + <T: SummableMultipliable> (m1: Matrix<T>, m2: Matrix<T>) -> Matrix<T> { ... }
    
    0 讨论(0)
  • 2020-12-05 08:44

    For Question 1 start by defining a protocol

    protocol Summable { func ignore () }
    

    It has a throw away method. Then add it as an extension to the things that you want to be summable.

    extension Int: Summable { func ignore () {} }
    

    [Note: I tried the above w/o a throw away method but got a failure; I suspect Swift needed something, anything in the protocol.]

    Now a test

     35> protocol Summable { func ignore () }
     36> extension Int: Summable { func ignore () {} }
     37> func testing<T: Summable> (x: T) -> T { return x }
     38> testing(1)
    $R16: (Int) = 1
     39> testing(1.2)
    <REPL>:39:1: error: cannot convert the expression's type '$T1' to type 'Summable'
    testing(1.2)
    ^~~~~~~~~~~~
    

    For Question 2, [edit] Use the following

    @infix func +<T: Summable> (m1: Matrix<T>, m2: Matrix<T>) -> Matrix<T> { ... }
    

    [Note: I tried the above in the REPL, which didn't work. But it works in a file (probably defines a 'global environment' which the REPL doesn't)]

    0 讨论(0)
提交回复
热议问题