【问题标题】:Swift generics and specializationSwift 泛型和专业化
【发布时间】:2017-07-10 21:47:30
【问题描述】:

我意识到 Swift 泛型不像 C++ 模板,其中代码是专门化并在实例化时生成的,但有没有办法让以下代码专门化第二次调用?

func X1<R>(i: R) {
    print("R")
}

func X1(i: Int) {
    print("Int")
}

func X2<R>(i: R) {
    X1(i: i)
}

X2(i: "s")
X2(i: 1)
X1(i: "s")
X1(i: 1)

具体来说,我看到的输出是:

R
R
R
Int

但我真的希望 X2 对 X1 for Int 的调用专门针对 X1 Int:

R
Int
R
Int

我知道我可以通过创建另一个以 Int 作为类型的 X2 来做到这一点,但我希望避免这种情况。

编辑 一些答案建议为每个特殊类型添加处理(即添加func X2(i: Int) 或进行类型转换let x = i as? Int)——这就是我试图避免的可能是很多专门的类型,例如:

func X1(i: Double) {
    print("Double")
}

func X1(i: Bool) {
    print("Bool")
}

func X1(i: Float) {
    print("Float")
}

【问题讨论】:

  • 在我测试的每个 Swift 版本中,我得到了“R”、“R”、“R”、“Int”。 (斯威夫特 3.0、3.0.1、3.1、3.1.1、4.0)
  • 抱歉,修正了输出。
  • 是否有特殊原因需要重载一个函数以使通用版本和具体版本都存在?

标签: swift generics


【解决方案1】:

您可以尝试在 X2 中投射 R:

func X2<R>(i: R) { 
   if let x = i as? Int { 
       X1(i: x) 
   } else { 
       X1(i: i) 
   } 
}

这将强制调用 X1 的 Int 版本。由于编译器会将泛型特化掉,所有的转换都可能会消失。

根据具体情况,您可能可以使用带有关联类型约束的协议扩展来解决此问题。

【讨论】:

  • 谢谢,但这似乎并不比为 X2 添加一堆专业化更好。
【解决方案2】:

我只是通过将 X2 专门用于 Int 类型来使其工作:

func X1<R>(i: R) {
    print("Any")
}
func X1(i: Int) {
    print("Int")
}

func X2<R>(i: R) {
    X1(i: i)
}
func X2(i: Int) {
    X1(i: i)
}

X2(i: "s")
X2(i: 1)
X1(i: "s")
X1(i: 1)

【讨论】:

  • 谢谢,但这就是我已经提到的——我只能通过专业化 X2 来做到这一点,如果我对 X1 有很多专业化,这并没有真正的帮助。
猜你喜欢
  • 2012-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多