【问题标题】:Literals in Swift genericsSwift 泛型中的文字
【发布时间】:2023-03-19 20:56:01
【问题描述】:

我正在尝试在 Swift 中实现一个通用的符号函数,以便它可以与任何浮点类型一起使用:

func sign<T> (value:T) -> T {
    if value < 0.0 {
        return -1.0
    }
    if value > 0.0 {
        return 1.0
    }
    return 0.0
}

但是这个错误阻碍了:

二元运算符“

【问题讨论】:

    标签: ios swift generics swift2


    【解决方案1】:

    如果您将T 限制为SignedNumberType,您将能够做任何您想做的事情。它继承自 Comparable 并且可以从整数文字转换,这是您需要的两件事。

    func sign<T: SignedNumberType> (value:T) -> T {
        if value < 0 {
            return -1
        }
        if value > 0 {
            return 1
        }
        return 0
    }
    

    【讨论】:

    • SignedNumberType 不包括 Double 参数的初始化器,因此单独使用此方法; value &lt; 0.0 比较很难通用。
    • 如果您与 0 而不是 0.0 进行比较,它将正常工作。返回值也是如此。
    • 啊,你是对的,他在上面的例子中只使用整数文字(作为双精度数),我的错!
    • 我的问题是关于 Swift 泛型中的浮点文字。这个答案对于实现符号功能很有用。
    • @DesmondHume ?? Nate 定义的符号,也适用于 Double 和 Float!返回类型将与函数的参数类型相同。如果您正在寻找其他东西,那就去做吧……然后再问。
    【解决方案2】:

    您可以创建一个类型约束(下面的MyFloats),您的浮点类型符合。你让这个类型约束本身符合Comparable,这样你就可以在比较泛型的值时使用小于二元中缀运算符&lt;。此外,对于上面给出的示例,MyFloats 类型约束只需要包含一个蓝图; Double 参数的初始化程序。对于DoubleFloatCGFloat 类型,此初始化程序已经存在,但由于协议无法知道哪些类型符合,因此您需要包含此蓝图。

    protocol MyFloats : Comparable {
        init(_ value: Double)
    }
    
    extension Double : MyFloats { }
    extension Float : MyFloats { }
    extension CGFloat : MyFloats { }
    
    func sign<T: MyFloats> (value:T) -> T {
        if value < T(0.0) {
            return T(-1.0)
        }
        if value > T(0.0) {
            return T(1.0)
        }
        return T(0.0)
    }
    

    【讨论】:

    • @DesmondHume 乐于助人。请注意,由于您的 sign 函数仅包含实际上可以表示为整数文字的“双文字”(1.010.00 等),我相信 Nate Cooks 下面的解决方案会对您来说更可取,因为您无需创建自定义协议并将类型扩展到此。但是请注意,SignedNumberType 解决方案将允许所有符合此协议的类型(不仅仅是浮点类型)调用您的函数sign
    • ... 如果您使用 Nates 解决方案但只希望它可用于浮点数(DoubleFloatCGFloat),您可以在下面的解决方案中修改类型约束增加对协议FloatingPointType:func sign&lt;T: protocol&lt;SignedNumberType, FloatingPointType&gt;&gt; ( ...的一致性
    • 您的回答的交互作用比其他人更能告诉我关于 Swift 的信息,而且这个解决方案更灵活地应用于其他目的。
    • 好的!我会将这些 cmets 留给可能需要较少类型约束自定义的线程访问者(-> Nates 回答)。
    【解决方案3】:

    this的回答。对于您的用例,您需要创建一个新的 protocol 扩展 Comparable 并使用 extension 扩展 FloatDouble Swift 类型。

    你终于可以使用这个协议作为泛型参数的条件了。

    func sign<T : MyCustomNumberProtocol> (value:T) -> T
    

    【讨论】:

    • 这将无法解决上述问题,因为协议NumericType(在链接线程中)不明确符合Comparable,因此不能仅从MyCustomNumberProtocol 推断出&lt; 运算符的存在.
    • @dfri 谢谢,这是真的!我在描述中忘记了这一步。现在我已经根据这个事实更新了我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多