Generics with Protocol

Hi,

I have 2 Generic structs Car1 and Car2.

I am not sure why Car1.f1 throws a compilation error while Car2 compiles successfully.

protocol P1 : RawRepresentable, CaseIterable, Hashable where RawValue == String {
    
}

struct Car1<T : RawRepresentable, CaseIterable, Hashable> where T.RawValue == String {

    //Throws a compilation error
    func f1(list: [T : String]) { //Type 'T' does not conform to protocol 'Hashable'

    }
}


struct Car2<T : P1> {
    
    func f1(list: [T : String]) {

    }
}

Question:

  • Am I missing something for Car1 ? I was thinking both would compile successfully.

Thanks,
somu

struct Car1<T: RawRepresentable & CaseIterable & Hashable> where T.RawValue == String {

    func f1(list: [T : String]) {

    }
}

It should be & here.

2 Likes

Wow, thank you so much !!! was breaking my head over it.

Just curious what happens when , is specified, does it do anything at all ?

, can only be used in codes like this

enum Test: Int, RawRepresentable, CaseIterable, Hashable {
    case a
}
struct Car1<T: RawRepresentable, CaseIterable, Hashable> where T.RawValue == String {

    func f1(list: [T : String]) {

    }
}
// is same to
struct Car1<T: RawRepresentable, A, B> where T.RawValue == String {

    func f1(list: [T : String]) {

    }
}
1 Like

What you are doing here :

struct Car1<T : RawRepresentable, CaseIterable, Hashable> where T.RawValue == String

… is declaring three generic parameter placeholders : the first T has to implement RawRepresentable, the second is a new placeholder called CaseIterable and the third is also a new placeholder called Hashable. Because of the commas, these last two do not represent existing types, they are new types with a scope restricted to the generic type.

As @linqingmo says, you might as well have used struct Car1<T: RawRepresentable, A, B>

If you really wanted to declare a generic struct whose generic parameter implemented those three protocols, and you already have a protocol that combines them, then why not simply write :

protocol P1 : RawRepresentable, CaseIterable, Hashable where RawValue == String { }

struct Car1<T : P1>
{
  …
}
3 Likes

@linqingmo @Joanna_Carter, thank you so much, now I get it.

I didn't realise , was used to separate template parameters. No wonder there were no compilation errors.

@Joanna_Carter I agree, I could make it more readable by declaring P1.