1

数値の演算子を作成しようとしています。たとえば、数値を 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
}

しかし、コンパイルに失敗しました。誰にもアイデアはありますか?

4

2 に答える 2

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
}
于 2015-07-04T08:20:13.410 に答える
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準拠する必要があることに注意してください。IntegerLiteralConvertible10

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 
}
于 2015-07-04T12:54:46.713 に答える