无法显式专门化泛型函数,多个泛型

时间:2019-07-17 13:41:13

标签: swift

关于我的问题,有很多答案,但是我为他们尝试的解决方案并未完全解决问题。我不确定这是否与具有多个泛型或其他特性有关(也是Swift的较新版本,因此请全神贯注于语法)。

我在我的API请求代码中注意到了很多共性,所以我决定将主要工作抽象出来,并使其与任何可编码的请求/响应对象一起使用。这是我的主要请求方法:

private func sendRequest<T: Encodable, U: Decodable>(url: URL, requestModel: T) -> Promise<U> 

我正在这样称呼它:

public func signIn(requestModel: SignInRequest) -> Promise<SignInResponse> {
    let url = URL(string: authURL + "/signin")!

    //getting compile error "Cannot explicitly specialize generic function" on this line
    return sendRequest<SignInRequest, SignInResponse>(url: url, requestModel: requestModel)
}

我尝试直接分配给返回对象:

let x : Promise<SignInResponse> = sendRequest(...)
return x

帮助编译器解决(如其他解决方案中所述),但仍然存在相同的问题。有见识吗?

2 个答案:

答案 0 :(得分:0)

我最终根据以下帖子使用了一种解决方案:https://stackoverflow.com/a/36232002/1088099

我显式传递了请求和响应对象类型作为参数:

private func sendRequest<T: Encodable, U: Decodable>(requestModelType: T.Type, responseModelType: U.Type, url: URL, requestModel: T) -> Promise<U> 

并致电:

public func signIn(requestModel: SignInRequest) -> Promise<SignInResponse> {
    let url = URL(string: authURL + "/signin")!

    return sendRequest(requestModelType:SignInRequest.self,
                       responseModelType:SignInResponse.self,
                       url: url,
                       requestModel: requestModel)
}

不是我所希望的解决方案,但可以解决问题。

答案 1 :(得分:0)

如果您为函数的参数提供足够的上下文来确定所有通用参数,则推断将成功。

从您的代码中,我怀疑不是这种情况,因为通用类型U既没有作为参数出现,也没有附加的类型约束来指定它。因此,编译器无法从函数调用中推断出函数返回值的具体类型是什么。

因此,如果TU之间存在关联,则可以将其用作附加约束,以在找到UT来“帮助”编译器推断。这是一个最小的示例:

protocol Foo {
  associatedtype Bar
  var bar: Bar { get }
}

struct FooImpl: Foo {
  let bar: Int = 0
}

func f<T, U>(foo: T) -> U where T: Foo, U == T.Bar  {
  return foo.bar
}

let a = f(foo: FooImpl())

协议Foo具有关联的类型Bar。通过在函数f的签名中使用此关联以对其返回类型添加约束,当我使用{的实例调用它时,Swift的编译器现在可以完全推断f的专用签名。 {1}}。


在您的特定示例中,我建议编写一个FooImpl参数应向其确认的协议,并使用关联的类型对返回值施加约束。 例如:

requestModel