Skip to content

Commit d6f1166

Browse files
authored
Merge pull request #62243 from apple/egorzhdan/cxx-convertible
[cxx-interop] Add `CxxConvertibleToCollection` protocol
2 parents 279e241 + 3e1a6dc commit d6f1166

File tree

3 files changed

+111
-0
lines changed

3 files changed

+111
-0
lines changed

stdlib/public/Cxx/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
add_swift_target_library(swiftCxx ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_SDK_OVERLAY
2+
CxxConvertibleToCollection.swift
23
CxxRandomAccessCollection.swift
34
CxxSequence.swift
45

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
/// A C++ type that can be converted to a Swift collection.
14+
public protocol CxxConvertibleToCollection {
15+
associatedtype RawIterator: UnsafeCxxInputIterator
16+
17+
/// Do not implement this function manually in Swift.
18+
mutating func __beginUnsafe() -> RawIterator
19+
20+
/// Do not implement this function manually in Swift.
21+
mutating func __endUnsafe() -> RawIterator
22+
}
23+
24+
@inlinable @inline(__always)
25+
internal func forEachElement<C: CxxConvertibleToCollection>(
26+
of c: C,
27+
body: (C.RawIterator.Pointee) -> Void
28+
) {
29+
var mutableC = c
30+
withExtendedLifetime(mutableC) {
31+
var rawIterator = mutableC.__beginUnsafe()
32+
let endIterator = mutableC.__endUnsafe()
33+
while rawIterator != endIterator {
34+
body(rawIterator.pointee)
35+
rawIterator = rawIterator.successor()
36+
}
37+
}
38+
}
39+
40+
extension Array {
41+
/// Creates an array containing the elements of a C++ collection.
42+
///
43+
/// This initializer copies each element of the C++ collection to a new Swift
44+
/// array.
45+
///
46+
/// - Complexity: O(*n*), where *n* is the number of elements in the C++
47+
/// collection.
48+
public init<C: CxxConvertibleToCollection>(_ c: C)
49+
where C.RawIterator.Pointee == Element {
50+
51+
self.init()
52+
forEachElement(of: c) { self.append($0) }
53+
}
54+
}
55+
56+
extension Set {
57+
/// Creates an set containing the elements of a C++ collection.
58+
///
59+
/// This initializer copies each element of the C++ collection to a new Swift
60+
/// set.
61+
///
62+
/// - Complexity: O(*n*), where *n* is the number of elements in the C++
63+
/// collection.
64+
public init<C: CxxConvertibleToCollection>(_ c: C)
65+
where C.RawIterator.Pointee == Element {
66+
67+
self.init()
68+
forEachElement(of: c) { self.insert($0) }
69+
}
70+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-experimental-cxx-interop)
2+
//
3+
// REQUIRES: executable_test
4+
// REQUIRES: OS=macosx || OS=linux-gnu
5+
6+
import StdlibUnittest
7+
import CustomSequence
8+
import Cxx
9+
10+
var CxxSequenceTestSuite = TestSuite("CxxConvertibleToCollection")
11+
12+
extension SimpleSequence: CxxConvertibleToCollection {}
13+
14+
CxxSequenceTestSuite.test("SimpleSequence to Swift.Array") {
15+
let seq = SimpleSequence()
16+
let array = Array(seq)
17+
expectEqual([1, 2, 3, 4] as [Int32], array)
18+
}
19+
20+
CxxSequenceTestSuite.test("SimpleSequence to Swift.Set") {
21+
let seq = SimpleSequence()
22+
let set = Set(seq)
23+
expectEqual(Set([1, 2, 3, 4] as [Int32]), set)
24+
}
25+
26+
extension SimpleEmptySequence: CxxConvertibleToCollection {}
27+
28+
CxxSequenceTestSuite.test("SimpleEmptySequence to Swift.Array") {
29+
let seq = SimpleEmptySequence()
30+
let array = Array(seq)
31+
expectTrue(array.isEmpty)
32+
}
33+
34+
CxxSequenceTestSuite.test("SimpleEmptySequence to Swift.Set") {
35+
let seq = SimpleEmptySequence()
36+
let set = Set(seq)
37+
expectTrue(set.isEmpty)
38+
}
39+
40+
runAllTests()

0 commit comments

Comments
 (0)