我正在尝试为数字创建运算符。例如,将数字递增10的运算符。
这是我写的代码:
prefix operator +++{}
prefix operator +++<T>(inout operand: T) -> T{
operand += 10
return operand
}
我的+=
运营商出错。它需要数字操作数。所以我这样做了:
protocol Numeric {}
extension Int: Numeric {}
extension Float: Numeric {}
extension Double: Numeric {}
prefix operator +++ {}
prefix operator +++<T: Numeric>(inout operand: T) -> T {
operand += 10
return operand
}
但它无法编译。有人有什么想法吗?
答案 0 :(得分:5)
这是一种更清洁,更好的方式,适用于从Int8
到CGFloat
的所有内容,并且只使用标准库类型,因此您不需要手动符合自己的协议:
prefix operator +++ {}
prefix func +++<T where T: FloatingPointType, T.Stride: FloatingPointType>(inout operand: T) -> T {
operand = operand.advancedBy(T.Stride(10))
return operand
}
prefix func +++<T where T: IntegerArithmeticType, T: IntegerLiteralConvertible, T.IntegerLiteralType: IntegerLiteralConvertible>(inout operand: T) -> T {
operand = operand + T(integerLiteral: 10)
return operand
}
正如@Airspeed Velocity指出你也可以这样做:
prefix operator +++ {}
prefix func +++<T: Strideable>(inout operand: T) -> T {
operand = operand.advancedBy(10)
return operand
}
答案 1 :(得分:1)
问题是您的Numeric
协议不保证+=
运营商会出现。
考虑一下:
// Numeric imposes no requirements, so this will compile
extension Range: Numeric { }
// but Range has no += operator, so +++ could not work
相反,您必须添加+=
作为Numeric
:
protocol Numeric: IntegerLiteralConvertible {
func +=(inout lhs: Self,rhs: Self)
}
注意,您还需要Numeric
符合IntegerLiteralConvertible
,以便您可以创建适当类型的10
以添加到其中。
现在,这个编译并运行正常,因为Numeric
保证它所使用的所有功能都可用:
prefix operator +++{}
prefix func +++<T: Numeric>(inout operand: T) -> T {
operand += 10
return operand
}
var i = 10
+++i // i is now 20
也就是说,已经有一个协议可以满足您的需求:Strideable
,所有标准数字类型都符合这些协议。
protocol Strideable {
// (actually _Strideable but don’t worry about that)
/// A type that can represent the distance between two values of `Self`.
typealias Stride : SignedNumberType
// note, SignedNumberType conforms to IntegerLiteralConvertible
/// Returns a `Self` `x` such that `self.distanceTo(x)` approximates
/// `n`.
///
/// - Complexity: O(1).
///
/// - SeeAlso: `RandomAccessIndexType`'s `advancedBy`, which
/// provides a stronger semantic guarantee.
func advancedBy(n: Self.Stride) -> Self
}
使用它的+=
的实现:
func +=<T : Strideable>(inout lhs: T, rhs: T.Stride)
这意味着您可以像这样实施+++
:
prefix func +++<T: Strideable>(inout operand: T) -> T {
operand = operand.advancedBy(10)
return operand
}