Вы не совсем сосредоточились на реальной проблеме. Исключим из примера все, что не имеет отношения к делу. Это компилируется и работает, как ожидалось:
struct TestFinder {
func doSomething<T,U>(_ function: (T,U) -> Void) -> Void {
print("two")
}
func doSomething<T,U,V>(_ function: (T,U,V) -> Void) -> Void {
print("three")
}
func doSomething<T,U,V,W>(_ function: (T,U,V,W) -> Void) -> Void {
print("four")
}
}
И здесь мы проверим это:
func f(_ s1: String, _ s2: String, _ s3: String, _ s4: String) -> Void {}
TestFinder().doSomething(f) // "four"
Но если вы добавите версию с одним переданным параметром функции , все ломается:
struct TestFinder {
func doSomething<T>(_ function: (T) -> Void) -> Void {
print("one")
}
func doSomething<T,U>(_ function: (T,U) -> Void) -> Void {
print("two")
}
func doSomething<T,U,V>(_ function: (T,U,V) -> Void) -> Void {
print("three")
}
func doSomething<T,U,V,W>(_ function: (T,U,V,W) -> Void) -> Void {
print("four")
}
}
Теперь мы не можем скомпилировать, потому что версия первая рассматривается как кандидат. И действительно, если мы удалим другие версии, мы по-прежнему будем компилировать !
struct TestFinder {
func doSomething<T>(_ function: (T) -> Void) -> Void {
print("one")
}
}
Это странная часть. Мы по-прежнему компилируем, хотя и говорим:
func f(_ s1: String, _ s2: String, _ s3: String, _ s4: String) -> Void {}
TestFinder().doSomething(f)
Очевидно, что эта функция с четырьмя параметрами рассматривается компилятором как «подходящая» к объявлению только один generi c параметр.
Считаю это ошибкой. Думаю, я могу догадаться, что могло его вызвать; это могло быть связано с унаследованным списком параметров функции в виде кортежей. Эта функция f
«эквивалентна» функции, принимающей одиночный параметр, состоящий из четырехстрочного кортежа. Тем не менее, вы не можете вызвать function
внутри doSomething
с четырехстрочным кортежем; Я не могу найти способ назвать это вообще. 1059 *.
ОБНОВЛЕНИЕ: По совету команды Swift я протестировал 4 мая 2020 года с набором инструментов Swift 5.3 Development. С его помощью ваш код компилируется и ведет себя так, как ожидалось. Это действительно была ошибка, и она была исправлена как часть
https://bugs.swift.org/browse/SR-8563
Возвращаясь на мгновение к моей версии, мой код тоже компилируется и ведет себя как и ожидалось, присутствуют все четыре версии doSomething
. Однако обратите внимание, что если вы удалите все, кроме первой версии doSomething
, он все равно компилируется и запускается. Более того, вы можете вызвать function
с четырьмя параметрами, объединив их в кортеж и принудительно применив приведение, например:
struct TestFinder2 {
func doSomething<T>(_ function: (T) -> Void) -> Void {
print("one")
function(("manny", "moe", "jack", "henry") as! T)
}
}
Это, кажется, подтверждает мою догадку, что то, что вы видите, является следствием скрытый кортежный характер списка параметров функции. К такому же выводу можно прийти из обсуждения ошибки, относящейся к "разбиению на кортежи".