JWK
JWK

Reputation: 3780

Append to generic array in Swift

I have a protocol named Foo and a struct named Bar. Bar conforms to Foo.

protocol Foo {}    
struct Bar: Foo {}

Appending a Bar instance to an array of Bar works as expected.

var array = [Bar]()
array.append(Bar())

Now, I have a generic struct called Baz that's initialized with a type that conforms to Foo (e.g. Bar).

struct Baz<T: Foo> {
    private(set) var array = [T]()

    init() {
        if T.self is Bar.Type {
            // Error: Cannot invoke 'append' with an argument list of type (Bar)
            array.append(Bar())
        }
    }
}

Attempting to append to the array results in the following error:

Cannot invoke 'append' with an argument list of type (Bar)

Why doesn't this work as expected?

As an aside, the use case is something like this:

let bazBarStack = Baz<Bar>().array
let bazQuxStack = Baz<Qux>().array

Upvotes: 0

Views: 1458

Answers (2)

Michael
Michael

Reputation: 9044

You need to store objects in array, that are of type T. Therefore you should cast using as! T:

struct Baz<T: Foo> {
    private(set) var array = [T]()

    init() {
        if T.self is Bar.Type {
            array.append(Bar() as! T)
        }
    }
}

Upvotes: 1

BallpointBen
BallpointBen

Reputation: 13750

Because array holds elements of a single type T, which must conform to Foo but is not necessarily compatible with Bar. It looks like you wish to have an array that can hold anything conforming to Foo; in this case, get rid of the generics altogether and simply write

private(set) var array = [Foo]()

and then your init will be

init() {
    array.append(Bar())
}

Upvotes: 0

Related Questions