我试图制作一个包装另一个的集合,并将固定大小的子集合作为元素出售:
struct PartitionedCollection<C: RandomAccessCollection>: BidirectionalCollection {
typealias TargetCollection = C
let collection: C
let wholePartitionCount: C.IndexDistance
let stragglerPartitionCount: C.IndexDistance
let span: C.IndexDistance
init(on c: C, splittingEvery stride: C.IndexDistance) {
let (q, r) = c.count.quotientAndRemainder(dividingBy: stride)
collection = c
wholePartitionCount = q
stragglerPartitionCount = r.signum()
span = stride
}
var startIndex: C.IndexDistance {
return 0
}
var endIndex: C.IndexDistance {
return wholePartitionCount + stragglerPartitionCount
}
subscript(i: C.IndexDistance) -> C.SubSequence {
// If `C` was only a Collection, calls to `index` would be O(n) operations instead of O(1).
let subStartIndex = collection.index(collection.startIndex, offsetBy: i * span)
if let subEndIndex = collection.index(subStartIndex, offsetBy: span, limitedBy: collection.endIndex) {
return collection[subStartIndex ..< subEndIndex]
} else {
return collection[subStartIndex...]
}
}
func index(after i: C.IndexDistance) -> C.IndexDistance {
return i.advanced(by: +1)
}
func index(before i: C.IndexDistance) -> C.IndexDistance {
return i.advanced(by: -1)
}
}
似乎我可以将其设为RandomAccessCollection
。我更改了基本协议,并且操场编译器抱怨该类型不符合Collection
,BidirectionalCollection
和RandomAccessCollection
。我得到了最后一个的Fix-It存根。编译器添加3个副本:
var indices: CountableRange<C.IndexDistance>
在我删除其中两个副本之前,所有副本都标记为:
Type 'C.IndexDistance.Stride' does not conform to protocol 'SignedInteger'
即使我填写了该属性,我也会保留错误:
var indices: CountableRange<C.IndexDistance> {
return startIndex ..< endIndex
}
我认为C.IndexDistance
是Int
,它是自己的Stride
,应符合SignedInteger
。发生了什么事?我可以为indices
定义不同的类型吗?我应该定义一些其他成员以获得随机访问(以及哪些和如何)?
我尝试添加index(_:offsetBy:)
和distance(from:to:)
方法;没有帮助。我尝试将indices
更改为Range<C.IndexDistance>
;它也没有帮助,它使编译器拒绝将类型视为BidirectionalCollection
和RandomAccessCollection
。