Swoid中Void的等同替代品

时间:2018-04-13 21:01:06

标签: swift

如果EquatableBox<T>,我尝试将条件T一致性添加到Equatable类型。由于Swift.Void不是EquatableBox<Void>不是Equatable

struct Box<T> {
    //...
}

extension Box: Equatable where T: Equatable {

}

我可以将下面的新类型定义为解决方案:

public struct Empty: Equatable {

}

然后使用Box<Empty>代替Box<Void>,这样可行。但是,想知道是否有其他方法可以引入新类型。

更新 我尝试了这个,但它没有工作

struct Box<T> {
    //...
}

extension Box: Equatable where T: Equatable {
    static func ==(lhs: Box<T>, rhs: Box<T>) -> Bool {
        return true
    }
}
extension Box where T == Void {
    static func ==(lhs: Box<T>, rhs: Box<T>) -> Bool {
        return true
    }
}

我在编译期间遇到错误:FooBarBaz does not conform to protocol Equatable

enum FooBarBaz: Equatable { 
    case success(box: Box<Void>)
    // case success(box: Box<Int>) compiles as expected.
}

请注意我使用 Swift 4.1

1 个答案:

答案 0 :(得分:2)

  

我在编译过程中遇到错误:FooBarBaz不符合协议Equatable

这个半答案着重解释为什么你自己尝试过的方法不会(还)起作用。

目前,条件性一致性存在限制,这将限制您使用此特定技术来实现目标。引用SE-0143: Conditional conformances,在Swift 4.1中实现:

  

多重一致

     

Swift已经禁止尝试使相同类型符合的程序   两次相同的协议,例如:

     

...

     

现有的多重一致性禁令延伸至有条件   一致性,包括尝试遵守相同的协议   两种不同的方式。

     

...

     

overlapping conformances部分描述了一些内容   由多种一致性引入的复杂性,以证明其合理性   被排除在此提案之外。可以介绍后续提案   支持多种一致性,但也应该涵盖   相关的功能,如与...正交的私有一致性   条件一致性。

这不允许我们构建多个条件一致性,例如:

struct Box<T> { }

extension Box: Equatable where T == Void {
    static func ==(lhs: Box<T>, rhs: Box<T>) -> Bool {
        return true
    }
}

// error: redundant conformance of 'Box<T>' to protocol 'Equatable'
extension Box: Equatable where T: Equatable {
    static func ==(lhs: Box<T>, rhs: Box<T>) -> Bool {
        return true
    }
}

另一方面,如果我们看一下你自己的例子:

struct Box<T> { }

extension Box: Equatable where T: Equatable {
    static func ==(lhs: Box<T>, rhs: Box<T>) -> Bool {
        return true
    }
}

extension Box where T == Void {
    static func ==(lhs: Box<T>, rhs: Box<T>) -> Bool {
        return true
    }
}

// error: type 'Void' does not conform to protocol 'Equatable'
func foo<T: Equatable>(_ _: T) { print(T.self, "is Equatable") }
foo(Box<Void>())

Swift准确地确定Box<Void>不是Equatable:扩展名Box where T == Void并不意味着Box<Void>符合Equatable,因为它没有利用Box EquatableTVoid==的条件一致性(T只提供Void方法struct Box<T> { } extension Box: Equatable where T == () { static func ==(lhs: Box<T>, rhs: Box<T>) -> Bool { return true } } func foo<T: Equatable>(_ _: T) { print(T.self, "is Equatable") } foo(Box<Void>()) // Box<()> is Equatable Box

  

条件一致性表达了泛型类型的概念   仅在其类型参数满足时才符合特定协议   某些要求。

作为旁注,以下示例会产生预期结果:

Equatable

然而,特别是,如果T == () typedef() Void,即struct Box<T> { } extension Box: Equatable where T == Void { static func ==(lhs: Box<T>, rhs: Box<T>) -> Bool { return true } } func foo<T: Equatable>(_ _: T) { print(T.self, "is Equatable") } foo(Box<Void>()) // compiler crash ,则替换"use strict"; function Aircraft(a, b, c) { this.manufacturer = a; this.numberOfEngines = b; this.costPerEngine = c; } // Prototype modifications should happen outside of the // constructor function so that they are processed just // once and not every time the constructor is invoked. Aircraft.prototype.totalCost = function() { return this.numberOfEngines * this.costPerEngine; } // At this point, the prototype is all set, so calling the // constructor (which inherits from the prototype) creates // a new object instance that has inherited the method. let thunderbolt = new Aircraft('Republic', 1, 20000); console.log(thunderbolt.totalCost()); @ExceptionHandler的条件一致性,崩溃了编译器:

/error
  

断言失败:(isActuallyCanonicalOrNull()&amp;&amp;“形成CanType   出于非规范类型!“),函数CanType,

     

file /Users/buildnode/jenkins/workspace/oss-swift-4.1-package-osx/swift/include/swift/AST/Type.h,   第393行。

     

...

编辑:显然是一个(现已解决的)错误: