快速:通用重载,“更专业"的定义 [英] Swift: generic overloads, definition of "more specialized"

查看:79
本文介绍了快速:通用重载,“更专业"的定义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In the below example, why is the foo(f) call ambiguous? I understand that the second overload could also apply with P == (), but why isn't the first one considered more specialized, and therefore a better match?

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'"

推荐答案

我要说的问题是您没有 明确地 告诉编译器P == ()

I'd say your problem is that you don't explicitely tell the compiler that P == ()

在操场上尝试以下代码:

try the following code in a playground :

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<R>(_ f: () -> R)实际上是foo<P, R>(_ f: (P) -> R)的特化.

Since (Void) cannot be converted to (), I guess the compiler can't understand that foo<R>(_ f: () -> R) is actually a specialization of foo<P, R>(_ f: (P) -> R).

我建议您创建通用类型别名为您的函数类型,以帮助编译器了解您在做什么,例如. :

I suggest you create generic type aliases for your function types to help the compiler understand what you're doing eg. :

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

现在,您可以像这样定义函数:

Now you can can define your function like that :

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") }

,然后将它们与所需的任何闭包一起使用:

and then use them with any closure you want :

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"

但是您实际上可以只写:

But you can actually just write :

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") }

您将得到相同的结果.

这篇关于快速:通用重载,“更专业"的定义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆