[cxx-interop] Make CxxConvertibleToCollection.forEach public

This allows clients to iterate over a C++ container which doesn't provide random access with a `.forEach` call.

rdar://107995558
This commit is contained in:
Egor Zhdan
2023-04-13 16:25:31 +01:00
parent 9436899526
commit d5f5d4bd55
4 changed files with 41 additions and 2 deletions

View File

@@ -36,6 +36,11 @@ public let benchmarks = [
runFunction: run_CxxSetOfU32_to_Set,
tags: [.validation, .bridging, .cxxInterop],
setUpFunction: makeSetOnce),
BenchmarkInfo(
name: "CxxSetU32.forEach",
runFunction: run_CxxSetOfU32_forEach,
tags: [.validation, .bridging, .cxxInterop],
setUpFunction: makeSetOnce),
]
func makeSetOnce() {
@@ -58,4 +63,13 @@ public func run_CxxSetOfU32_to_Set(_ n: Int) {
}
}
@inline(never)
public func run_CxxSetOfU32_forEach(_ n: Int) {
for _ in 0..<n {
set.forEach {
blackHole($0)
}
}
}
#endif

View File

@@ -25,16 +25,26 @@ public protocol CxxConvertibleToCollection<Element> {
extension CxxConvertibleToCollection {
@inlinable
internal func forEach(_ body: (RawIterator.Pointee) -> Void) {
public func forEach(_ body: (RawIterator.Pointee) throws -> Void) rethrows {
var rawIterator = __beginUnsafe()
let endIterator = __endUnsafe()
while rawIterator != endIterator {
body(rawIterator.pointee)
try body(rawIterator.pointee)
rawIterator = rawIterator.successor()
}
}
}
// Break the ambiguity between Sequence.forEach and CxxConvertibleToCollection.forEach.
extension CxxConvertibleToCollection where Self: Sequence {
@inlinable
public func forEach(_ body: (Element) throws -> Void) rethrows {
for element in self {
try body(element)
}
}
}
extension RangeReplaceableCollection {
/// Creates a collection containing the elements of a C++ container.
///

View File

@@ -18,6 +18,12 @@ CxxCollectionTestSuite.test("SimpleCollectionNoSubscript as Swift.Collection") {
expectEqual(c[0], 1)
expectEqual(c[1], 2)
expectEqual(c[4], 5)
var array: [Int32] = []
c.forEach {
array.append($0)
}
expectEqual([1, 2, 3, 4, 5] as [Int32], array)
}
CxxCollectionTestSuite.test("SimpleCollectionReadOnly as Swift.Collection") {

View File

@@ -39,4 +39,13 @@ CxxSequenceTestSuite.test("SimpleEmptySequence to Swift.Set") {
expectTrue(set.isEmpty)
}
CxxSequenceTestSuite.test("SimpleSequence.forEach") {
let seq = SimpleSequence()
var array: [Int32] = []
seq.forEach {
array.append($0)
}
expectEqual([1, 2, 3, 4] as [Int32], array)
}
runAllTests()