【问题标题】:Swift: generic overloads, definition of "more specialized"Swift:泛型重载,“更专业”的定义
【发布时间】:2020-06-15 07:47:25
【问题描述】:

在下面的例子中,为什么foo(f) 调用不明确? 我知道第二个重载也适用于P == (), 但是为什么第一个不被认为更专业, 从而更好地匹配?

func foo<R>(_ f: () -> R) { print("r") }
func foo<P, R>(_ f: (P) -> R) { print("pr") }

let f: () -> Int = { 42 }
foo(f)   //  "Ambiguous use of 'foo'"

【问题讨论】:

    标签: swift generics overload-resolution


    【解决方案1】:

    我想说你的问题是你没有 explicitely 告诉编译器 P == ()

    在游乐场尝试以下代码:

    Void.self == (Void).self // true
    Void() == () // true
    (Void)() == () // true
    (Void) == () // Cannot convert value of type '(Void).Type' to expected argument type '()'
    
    Foo<Int>.self == (() -> Int).self // false
    (() -> Int).self == ((Void) -> Int).self // false
    Foo<Int>.self == ((Void) -> Int).self // true
    
    

    由于(Void)无法转换为(),我猜编译器无法理解foo&lt;R&gt;(_ f: () -&gt; R)实际上是foo&lt;P, R&gt;(_ f: (P) -&gt; R)的特化。

    我建议您为您的函数类型创建generic type aliases,以帮助编译器了解您在做什么,例如。 :

    typealias Bar<P, R> = (P) -> R
    typealias Foo<R> = Bar<Void, R>
    

    现在你可以这样定义你的函数了:

    func foo<R>(_ f: Foo<R>) { print("r") } // Note that this does not trigger a warning.
    func foo<P, R>(_ f: Bar<P, R>) { print("pr") }
    

    然后将它们与您想要的任何闭包一起使用:

    let f: () -> Int = { 42 }
    foo(f)   // prints "r"
    let b: (Int) -> Int = { $0 }
    foo(b) // prints "pr"
    let s: (String) -> Double = { _ in 0.0 }
    foo(s) // prints "pr"
    
    

    但实际上你可以只写:

    func foo<R>(_ f: (()) -> R) { print("r") }
    func foo<P, R>(_ f: (P) -> R) { print("pr") }
    

    甚至:

    func foo<R>(_ f: (Void) -> R) { print("r") } // triggers warning :
    // When calling this function in Swift 4 or later, you must pass a '()' tuple; did you mean for the input type to be '()'?
    func foo<P, R>(_ f: (P) -> R) { print("pr") }
    

    你会得到相同的结果。

    【讨论】:

    • 哦,很好。我缺少的关键见解是 (P0..Pn) -&gt; R((P0..Pn)) -&gt; R。非常感谢。
    • (有趣的是,同样的元组解构技巧似乎在泛型类的 init() 中不起作用。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多