How are multiple parameter packs to be handled?
Types don't have the problem because they're limited to one parameter pack.
struct S<T, each U, V> { }
_ = S<Bool, Int, String>() // Compiles
Functions require entupling all but the last parameter unless you use labels.
No labels:
func f<each T, each U, each V>(
_: (repeat (each T).Type),
_: (repeat (each U).Type),
_: repeat (each V).Type
) { }
f(Bool.self, (Int.self, Int.self), String.self)
Labels:
func f<each T, each U, each V>(
T: repeat (each T).Type,
U: repeat (each U).Type,
V: repeat (each V).Type
) { }
f(T: Bool.self, U: Int.self, Int.self, V: String.self)
I think there are four options?
- Have the labeling be optional, as with e.g. tuple labels
let tuple: (t: Bool, u: Int) = (true, 1)
f<Bool, U: Int, V: String>() // No `T:` there.
- Treat the placeholder names like subscript* argument labels, requiring the name being present twice.
func f<T each T, U each U, V each V>() { }
f<T: Bool, U: Int, V: String>()
* This sort of thing, I mean:
enum E {
static subscript(label label: some Any) -> Void { }
}
E[label: "value"]
- Continue to require metatype arguments for all but one of the pack arguments.
func f<each T, each U, each V>(
U: repeat (each U).Type,
V: repeat (each V).Type
)
f<Bool, _, _>(U: Int.self, Int.self, V: String.self)
(I loathe this option.)
- Disallow explicit specialization for functions that use multiple parameter packs.