在 Swift 中将泛型类型传递给函数

Passing generic type over functions in Swift

为了避免代码重复,我试图找到一种方法从 U.

类型的变量中推断参数类型 T() -> T

不知道我说的够不够清楚所以我不想这样:

func f<T>(closure: () -> T) -> String {
    return "closure: () -> \(T.self)"
}
func f<T>(value: T) -> String {
    return "value: \(T.self)"
}

f("test1") // -> "value: Swift.String"
f({ return "test2" }) // -> "closure: () -> Swift.String"

func foo<U>(bar: U) -> (String, String) {
    return ("\(U.self)", f(bar))
}

foo("test3") // (.0 "Swift.String", .1 "value: Swift.String")
foo({ return "test4" }) // (.0 "() -> Swift.String", .1 "value: () -> Swift.String")

我希望 foo({ return "test4" }) 调用 f<T>(closure: () -> T) 函数而不是 f<T>(value: T)。为什么 Swift 不能推断 bar: U() -> T 模式匹配?

TL;DR:foo() / U 丢失了类型数据。

我怀疑您有 C++ 背景。

这在 C++ 中有效,因为 C++ 根据调用站点推断类型。 Swift 不同,因为泛型参数是 唯一的 类型数据源。在您的情况下,您没有提供有关 U 类型的信息,因此编译器不知道如何将其转换为闭包类型。您对 f() 的值覆盖是有效的,因为您没有在 T 上放置任何条件,而在您的闭包类型覆盖中,您指定了一个特定的形式(闭包)。由于您通过 foo 调用采用泛型(想想空白)类型 U 的所有类型数据都丢失了,因此编译器没有足够的信息,并且无法推断出从(空白)到闭包的转换。

这是 "type reification" 的主题,在 devforums.apple.com 上对此进行了冗长的讨论。