Skip to content

Commit cad0475

Browse files
committed
[cxx-interop] Add std::set initializer that takes a Swift Sequence
rdar://107909624
1 parent 59cb6ad commit cad0475

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

lib/ClangImporter/ClangDerivedConformances.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -586,10 +586,33 @@ void swift::conformToCxxSetIfNeeded(ClangImporter::Implementation &impl,
586586
if (!valueType || !sizeType)
587587
return;
588588

589+
auto insertId = ctx.getIdentifier("__insertUnsafe");
590+
auto inserts = lookupDirectWithoutExtensions(decl, insertId);
591+
FuncDecl *insert = nullptr;
592+
for (auto candidate : inserts) {
593+
if (auto candidateMethod = dyn_cast<FuncDecl>(candidate)) {
594+
if (!candidateMethod->hasParameterList())
595+
continue;
596+
auto params = candidateMethod->getParameters();
597+
if (params->size() != 1)
598+
continue;
599+
auto param = params->front();
600+
if (param->getType()->getCanonicalType() !=
601+
valueType->getUnderlyingType()->getCanonicalType())
602+
continue;
603+
insert = candidateMethod;
604+
break;
605+
}
606+
}
607+
if (!insert)
608+
return;
609+
589610
impl.addSynthesizedTypealias(decl, ctx.Id_Element,
590611
valueType->getUnderlyingType());
591612
impl.addSynthesizedTypealias(decl, ctx.getIdentifier("Size"),
592613
sizeType->getUnderlyingType());
614+
impl.addSynthesizedTypealias(decl, ctx.getIdentifier("InsertionResult"),
615+
insert->getResultInterfaceType());
593616
impl.addSynthesizedProtocolAttrs(decl, {KnownProtocolKind::CxxSet});
594617
}
595618

stdlib/public/Cxx/CxxSet.swift

+20
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,31 @@
1313
public protocol CxxSet<Element> {
1414
associatedtype Element
1515
associatedtype Size: BinaryInteger
16+
associatedtype InsertionResult // std::pair<iterator, bool>
17+
18+
init()
19+
20+
@discardableResult
21+
mutating func __insertUnsafe(_ element: Element) -> InsertionResult
1622

1723
func count(_ element: Element) -> Size
1824
}
1925

2026
extension CxxSet {
27+
/// Creates a C++ set containing the elements of a Swift Sequence.
28+
///
29+
/// This initializes the set by copying every element of the sequence.
30+
///
31+
/// - Complexity: O(*n*), where *n* is the number of elements in the Swift
32+
/// sequence
33+
@inlinable
34+
public init<S: Sequence>(_ sequence: S) where S.Element == Element {
35+
self.init()
36+
for item in sequence {
37+
self.__insertUnsafe(item)
38+
}
39+
}
40+
2141
@inlinable
2242
public func contains(_ element: Element) -> Bool {
2343
return count(element) > 0

test/Interop/Cxx/stdlib/use-std-set.swift

+14
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,18 @@ StdSetTestSuite.test("MultisetOfCInt.contains") {
4747
expectFalse(s.contains(3))
4848
}
4949

50+
StdSetTestSuite.test("SetOfCInt.init()") {
51+
let s = SetOfCInt([1, 3, 5])
52+
expectTrue(s.contains(1))
53+
expectFalse(s.contains(2))
54+
expectTrue(s.contains(3))
55+
}
56+
57+
StdSetTestSuite.test("UnorderedSetOfCInt.init()") {
58+
let s = UnorderedSetOfCInt([1, 3, 5])
59+
expectTrue(s.contains(1))
60+
expectFalse(s.contains(2))
61+
expectTrue(s.contains(3))
62+
}
63+
5064
runAllTests()

0 commit comments

Comments
 (0)