【问题标题】:Cannot explicitly specialize a generic function when using closures使用闭包时无法显式特化泛型函数
【发布时间】:2018-07-13 13:33:29
【问题描述】:

我有这样的功能:

func register<T: Routable>(_ action: Action, withCallback callback: @escaping (T?) -> Void) {
    notificationCenter.addObserver(forName: actionMap[action], object: nil, queue: .main, using: { notification in
    let routable = T(userInfo: notification.userInfo)
        callback(routable)
    })
}

Routable 的定义如下:

protocol Routable {
    init?(userInfo: [AnyHashable: Any]?)
}

当我尝试使用它时,我收到了

无法显式特化泛型函数

这是用法:

controller.register<Navigate>(Action.navigate) { [unowned self] navigate in
    // do something
}

有什么办法能让编译器满意吗?

【问题讨论】:

    标签: swift generics


    【解决方案1】:

    我相信这纯粹是一个语法问题。你不能像这样直接传递类型参数。您需要“填写类型孔”。为此,您需要将类型添加到navigate

    controller.register(Action.navigate) { [unowned self] (navigate: Navigate?) in ... }
    

    有时这种语法很烦人,因为它掩盖了类型。您可以通过这种方式重写register 的签名来改进它:

    func register<T: Routable>(action: Action, returning: T.type,
                               withCallback callback: @escaping (T?) -> Void)
    

    你可以这样称呼它:

    controller.register(action: .navigate, returning: Navigate.self) { 
        [unowned self] navigate in 
        // ...
    }
    

    returning 参数不直接在函数中使用。它只是提供了一种更明确的方式来专门化函数。

    【讨论】:

    • 罗布,谢谢!最后,当我在考虑解决方案时,我选择了第二个。
    【解决方案2】:

    如果没有看到更完整的代码示例,真的很难说......但基本上编译器告诉你的是“你告诉我你希望 register 函数是通用的(因为它有一个类型参数)但是你还试图确切地告诉我要使用什么类型,我不喜欢那样”。

    当您在调用中添加特定类型参数时,您“显式地专门化 [ing]”该函数:

    controller.register<Navigate>...
    # Right Here       ^^^^^^^^^^
    

    编译器希望灵活地确定要调用的寄存器函数类型。我怀疑你想要的是:

    controller.register(Action.navigate) {...
    

    您没有明确专门化泛型函数,而是让编译器确定要使用的专门化。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多