在Swift中,如何为用户提供一种类型的min和max函数?

时间:2018-12-22 19:53:56

标签: swift generics scope max min

我正在将我的向量和几何数学库从C ++移植到swift,并且在处理泛型的类型约束时遇到困难。一个特别困难的是最小/最大。考虑一个非常简单的通用Vector2类:

public protocol Vectorable : Numeric & Initializable {}

extension Float : Vectorable {}
extension Double : Vectorable {}
extension Int32 : Vectorable {}

struct Vector2<T : Vectorable> : CustomStringConvertible, Equatable {

   var x : T
   var y : T

    ....
}

这是我(用户定义的全局范围内)min / max函数,是按组件定义的,它们对组件值调用标准库min / max:

func min <T : Comparable> (lhs : Vector2<T>, rhs : Vector2<T>) -> Vector2<T> {
   return Vector2<T>(min(lhs.x, rhs.x), min(lhs.y, rhs.y))
}

func max <T : Comparable> (lhs : Vector2<T>, rhs : Vector2<T>) -> Vector2<T> {
   return Vector2<T>(max(lhs.x, rhs.x), max(lhs.y, rhs.y))
}

但是,这不起作用。当我尝试在Vector2类型的值上使用这些min和max函数时,编译器发出以下不满消息:

  

src / math / Vector2.swift:167:19:错误:参数类型为'Vector2f'(aka   'Vector2')不符合预期的类型'Comparable'
  令d = min(a,b)

我不明白为什么Vector在这里需要符合Comparable。不,我在哪里不能对Vector对象调用全局min / max运算符,它仅适用于类型为T:可比较,实际上只是Float的组件。

似乎编译器正在忽略我的最小/最大定义,并尝试应用标准库版本。

1 个答案:

答案 0 :(得分:0)

尽管缺少必要的信息,但我还是可以通过省略和保留一些地方来重现该问题,例如:

<link href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.4.6/css/swiper.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.4.6/js/swiper.min.js"></script>

<div class="swiper-container swiper-scale-effect">
    <!-- Additional required wrapper -->
    <div class="swiper-wrapper">
        <!-- Slides -->
        <div class="swiper-slide">
      <div class="slide1 swiper-slide-cover"></div>
      <div>Slide 1</div>
    </div>
    <div class="swiper-slide">
      <div class="slide2 swiper-slide-cover"></div>
      <div>Slide 2</div>
    </div>
    <div class="swiper-slide">
      <div class="slide3 swiper-slide-cover"></div>
      <div>Slide 3</div>
    </div>
    <div class="swiper-slide">
      <div class="slide4 swiper-slide-cover"></div>
      <div>Slide 4></div>
    </div>
        ...
    </div>
    <!-- If we need pagination -->
    <div class="swiper-pagination"></div>

    <!-- If we need navigation buttons -->
    <div class="swiper-button-prev"></div>
    <div class="swiper-button-next"></div>

    <!-- If we need scrollbar -->
    <div class="swiper-scrollbar"></div>
</div>

这会向我们报告错误消息:

enter image description here

在这种情况下,问题仅仅是函数声明中省略的下划线:

public protocol Vectorable : Numeric {}

extension Float : Vectorable {}
extension Double : Vectorable {}
extension Int32 : Vectorable {}

struct Vector2<T : Vectorable> :  Equatable {
    var x : T
    var y : T
}

func min <T : Comparable> (lhs : Vector2<T>, rhs : Vector2<T>) -> Vector2<T> {
    return Vector2<T>(x:min(lhs.x, rhs.x), y:min(lhs.y, rhs.y))
}

func max <T : Comparable> (lhs : Vector2<T>, rhs : Vector2<T>) -> Vector2<T> {
    return Vector2<T>(x:max(lhs.x, rhs.x), y:max(lhs.y, rhs.y))
}


class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let v1 = Vector2(x: 1.0, y: 1.0)
        let v2 = Vector2(x: 2.0, y: 2.0)
        let v3 = min(v1,v2) // error
    }
}

func min <T : Comparable> (_ lhs : Vector2<T>, _ rhs : Vector2<T>) -> Vector2<T> {