【问题标题】:Strange type error with basic operator overloading基本运算符重载的奇怪类型错误
【发布时间】:2018-06-16 18:10:45
【问题描述】:

我正在编写结构来表示向量和矩阵,并使用一些运算符来处理它们。但是这些运算符的一些示例用法会产生我无法解释的类型错误。

这是我的库中的精简摘录(A 是矩阵类型,B 是向量类型,感兴趣的人可以使用):

struct A { }
struct B { }

func *(left: A, right: A) -> A { return A() }
func *(left: A, right: B) -> B { return B() }

let a: A = A()
let b: B = (a * a) * B()

在 Swift Playground 中运行它会产生以下编译器错误:

error: Test.playground:2:20: error: 'A' is not convertible to 'B'
let b: B = (a * a) * B()
           ~~~~~~~~^~~~~

内联一些变量,将a * a 提取为单独的变量和/或在某些情况下从变量中删除类型注释可以解决错误或产生不同的错误。

我不是在寻找解决方法,我只是想了解这里发生了什么,是我做错了什么还是我是否在编译器中发现了错误。

我正在运行 Xcode 9.2。

【问题讨论】:

  • 大声笑这也有效:{ a * a }() * B(){ $0 * $0 }(a) * B() :p

标签: swift types operator-overloading


【解决方案1】:

这对我来说似乎是一个错误。如果我们省略类型注释(其中 无论如何都不需要):

let a = A()
let b = (a * a) * B()

然后编译器抱怨“模糊使用”:

main.swift:14:12: error: ambiguous reference to member '*'
let b = (a * a) * B()
           ^
main.swift:7:6: note: found this candidate
func *(left: A, right: A) -> A { return A() }
     ^
main.swift:8:6: note: found this candidate
func *(left: A, right: B) -> B { return B() }
     ^
Swift.Float:4:24: note: found this candidate
    public static func *(lhs: Float, rhs: Float) -> Float
                       ^
Swift.Double:4:24: note: found this candidate
    public static func *(lhs: Double, rhs: Double) -> Double

Swift.Float80:4:24: note: found this candidate
    public static func *(lhs: Float80, rhs: Float80) -> Float80
                       ^
Swift.UInt8:234:24: note: found this candidate
    public static func *(lhs: UInt8, rhs: UInt8) -> UInt8
                       ^
Swift.Int8:234:24: note: found this candidate
    public static func *(lhs: Int8, rhs: Int8) -> Int8

// ... and many more  ...

这没有意义,因为这些重载不适用 到两个A 操作数。

看来编译器“糊涂”了,因为有这么多 * 运算符的重载定义。问题不 使用自定义运算符发生,编译没有问题:

infix operator <*>: MultiplicationPrecedence

struct A { }
struct B { }

func <*>(left: A, right: A) -> A { return A() }
func <*>(left: A, right: B) -> B { return B() }

let a = A()
let b = (a <*> a) <*> B()

我建议在https://bugs.swift.org 提交错误,并使用中间 变量:

let a = A()
let a2 = a * a
let b = a2 * B()

或中间演员:

let a = A()
let b = ((a * a) as A) * B()

作为一种解决方法。

【讨论】:

  • 我认为您对使用自定义运算符时不会发生此错误的观察非常有趣!对于我拥有的用例,使用中间转换似乎是一个不错的解决方法。谢谢!
猜你喜欢
  • 2014-02-02
  • 2013-09-06
  • 1970-01-01
  • 2019-11-17
  • 2015-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多