J.Doe
J.Doe

Reputation: 1552

Integer conversion to generic type for calculating average. Non-nominal type does not support explicit initialization

I am trying to create a generic Queue class that has an average function however I am having trouble doing so because I need a protocol that somehow says that T(Int) is a valid operation.

This was my attempt

class Queue<T:Numeric & Comparable> {
    private var array:[T]
    .....
    func average() -> T {
        return sum() / T(array.count)
    }
}

However for obvious reasons the compiler says that I cant do that because T does not support explicit initialization. What is the name of a protocol that implements this behavior or how can I code my own?

Upvotes: 1

Views: 101

Answers (1)

Leo Dabus
Leo Dabus

Reputation: 236458

Note that Numeric Protocol also includes FloatingPoint types, so you should constrain your Queue generic type to BinaryInteger. And regarding your average return type you should return Double instead of the generic integer. Your Queue class should look like this:

class Queue<T: BinaryInteger & Comparable> {
    private var array: [T] = []
    init(array: [T]) {
        self.array = array
    }
    func sum() -> T {
        return array.reduce(0, +)
    }
    func average() -> Double {
        return array.isEmpty ? 0 : Double(Int(sum())) / Double(array.count)
    }

    // If you would like your average to return the generic type instead of Double you can use numericCast method which traps on overflow and converts a value when the destination type can be inferred from the context.
    // func average() -> T {
    //     return sum() / numericCast(array.count)
    // }

}

Playground Testing

let queue = Queue(array: [1,2,3,4,5])
queue.sum()       // 15
queue.average()   // 3

If you would like to extend an array of Numeric, BinaryInteger or FloatingPoint types you can check this answer.

Upvotes: 1

Related Questions