Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic copy function in Swift

Tags:

generics

swift

I'm trying to make a generic Swift function that would accept two collections and copy a part of one to a part of the other, kind of like std::copy in terms of semantics and memcpy in terms of interface. However, I find myself unable to come up with the correct generic arguments/function arguments to make it work.

The goal is to be able to call it like that, possibly omitting any of the three last parameters:

copy(&output, input, offsetA: 0, offsetB: 4, count: 20)

This is what I have so far:

func copy
    <T: CollectionType, U: CollectionType where
        T.Generator.Element == U.Generator.Element,
        T.Index == Int, T.Index == U.Index,
        T.Generator.Element: Equatable>
    (inout a: T, b: U, offsetA: Int = 0, offsetB: Int = 0, count: Int? = nil) {
    let max = count ?? b.endIndex - b.startIndex - offsetB
    for i in 0..<max {
        let indA = offsetA + i
        let indB = offsetB + i
        a[indA] = b[indB]
    }
}

However, I have this error on the a[indA] = b[indB] line:

Could not find an overload for 'subscript' that accepts the supplied arguments

This is somewhat surprising as nearly identical generic constraints allow me to compare elements, meaning that the type should be right, at least.

What am I missing? Otherwise, is there already a function to do this elsewhere?

like image 313
zneak Avatar asked May 02 '26 15:05

zneak


1 Answers

That error is because CollectionType doesn’t provide an assignable subscript. Switch T to conform to MutableCollectionType, which adds one.

P.S. you could switch T.Index == Int for T.Index: RandomAccessIndexType if you want to make it a bit more generic. That might entail fiddling with the calcuation of max a bit.

Also I think you can ditch the requirement for the elements to be equatable, I don’t think you’re using it. But remember, it’ll be a shallow copy if the elements are classes.

You might want to look at the ExtensibleCollectionType protocol, which adds the ability to create fresh empty collections of that type, and to append new elements to them, and RangeReplaceableCollectionType, which adds the ability to update ranges in collections with values from other collections (as well as delete ranges of elements, insert new elements etc).

like image 188
Airspeed Velocity Avatar answered May 05 '26 08:05

Airspeed Velocity



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!