Swift init 中的通用约束

Swift Generic constraints in init

我有泛型,我希望能够使用特定约束对其进行初始化。约束仅用于初始化。 class 的其余部分不在乎。这是一个简化的例子:

struct Generic<T> {
  let compare: (T, T) -> Bool
  init<T: Equatable>(data: [T]) {
    let handler: (T, T) -> Bool = { [=11=] ==  }
    compare = handler
    insert(data)
  }

  init(compareHandler: (T, T) -> Bool, data[T]) {
    compare = self.compareHandler
    insert(data)
  }
}

你可以看到有两个初始化器。第二个显然工作正常。但是,在第一个中,局部类型 T 与结构的泛型类型不匹配。因此,例如,尝试插入数据时我得到 Cannot invoke 'insert' with an argument list of type '([T])'。我是否可以将 Struct 的泛型类型专门用于初始化或特定函数?

请注意,我已经尝试 init<T where T:Equatable>(data: [T]) 达到同样的效果。

更新

我正在使用以下解决方法:我创建了一个顶级函数并删除了专门的初始化:

func equatableHandler<T: Equatable>(left: T, right: T) -> Bool {
  return left == right
}

该结构的客户端可以使用以下方式进行初始化:Generic(compareHandler: equatableHandler, data: data)

它不完全是使用专门 init 的 "convenience",但我想它对我的目的来说已经足够好了。我不喜欢创建顶级函数,但是泛型经常用于 "Equatable" 泛型,所以我定义一次处理程序供客户使用是有意义的。

问题是第一个init方法

init<T: Equatable>(data: [T]) 

引入了一个本地类型占位符 T 隐藏(并且完全 与 Generic 类型的占位符 T 无关,所以它 本质上与 Array extension to remove object by value.

中的问题相同

从 Swift 2 开始,您可以使用 "restricted extension":

来解决这个问题
extension Generic where T : Equatable {
    init(data: [T]) {
        let handler: (T, T) -> Bool = { [=11=] ==  }
        compare = handler
        // ...
    }
}

对于Swift 1.x,唯一的解决方案可能是定义一个全局助手 函数

func makeGeneric<T : Equatable>(data: [T]) -> Generic<T> {
    return Generic(compareHandler:  { [=12=] ==  }, data: data)
}

(我想不出一个合理的函数名称 :)。