Supported Features and Constraints of C++ Interoperability
Swift supports bidirectional interoperability with C++. This page describes which C++ interoperability features are currently supported. It also talks about the limitations in the current support for C++ interoperability. Additionally, it lists the set of constraints that are related to C++ interoperability support.
C++ interoperability is an actively evolving feature of Swift. Certain aspects of its design and functionality might change in future releases of Swift, as the Swift community gathers feedback from real world adoption of C++ interoperability in mixed Swift and C++ codebases. This page is going to be updated whenever a new release of Swift changes the supported set of C++ interoperability features.
Platform Support
C++ interoperability is supported for development and deployment on all platforms that Swift supports.
Minimum Deployment Version for Mixed-Language Application
C++ interoperability does not impose additional deployment version requirements for your application, except when your Swift code uses C++ classes or structures that become reference types. The minimum deployment version for an application that does not use such reference types is the same as Swift’s regular minimum deployment version.
Minimum Deployment Version for Reference Types Imported from C++
The table below shows the minimum OS version for which a mixed Swift and C++ application that uses C++ classes or structures that become reference types can be deployed. Any deployment platform not listed in the table below is supported automatically, so the imported reference types do not impose addition deployment version requirements for platforms like Ubuntu or CentOS.
Platform running Swift application | Minimum deployment version |
---|---|
macOS | 13.3 |
iOS | 16.4 |
watchOS | 9.4 |
tvOS | 16.4 |
Compiler Support
C++ interoperability is supported in Swift 5.9 and above.
Swift’s support for bidirectional interoperability relies on a header generated by the Swift compiler that can then be included by C++ code that wants to use Swift APIs. This header uses Swift-specific compiler extensions that are supported only by the following C++ compilers:
- Clang (starting with LLVM 11 and above)
- Apple Clang
C++ code built with other compilers cannot call Swift functions or use Swift types from C++.
C++ Standard Library Support
Swift compiler uses the platform’s default C++ standard library when interoperating with C++. This table shows which C++ standard library is used when building Swift code for a specific deployment platform:
Platform running Swift application | Default C++ Standard Library |
---|---|
Apple platforms | libc++ |
Ubuntu, CentOS, Amazon Linux | libstdc++ |
Windows | Microsoft C++ Standard Library (msvcprt) |
Swift does not currently support selecting an alternative standard library for platforms that support alternative standard libraries. For example, you can’t use libc++ when building Swift code for Ubuntu, even though libc++ can be used when building C++ code for Ubuntu.
Mixed Swift and C++ code must use the same C++ standard library.
Using C++ interoperability requires a compiler with enabled support for the C++14 standard or a newer version. Swift allows you to change which version of the C++ standard it uses; however, the C++ library headers used from Swift must also conform to the selected C++ standard. When using bidirectional interoperability, programs need to be compiled with C++14 support, since the generated C++ interface for a Swift module uses C++14 features.
Customizing the C++ Standard Version
Here’s how to set the version of the C++ standard used for interoperability by the Swift compiler:
- When compiling package dependencies, the C++ standard version can be
customized in
Package.swift
using thecxxLanguageStandard
parameter in yourPackage(...)
. - For Xcode targets, you can choose the C++ standard used from the C++ Language Dialect setting in the Build Settings tab.
- If you’re using a different build system or invoking the
swiftc
Swift compiler directly from the command line, you can specify a C++ standard version with the-Xcc -std=
option, for example,-Xcc -std=c++20
.
Supported C++ APIs
This section describes which C++ APIs are supported in Swift.
C++ Functions Supported in Swift
Swift supports calling most non-templated:
- Top-level functions
- Functions inside of namespaces
- Member functions, both instance and static
- Virtual member functions of C++ types that become reference types
- Constructors
- Operators
- Arithmetic operators, like
operator+
,operator-
,operator*
- Pre-increment operator
operator++
is represented asfunc successor() -> Self
- Call operator
T operator(Param p)
is represented asfunc callAsFunction(p: Param) -> T
- Bool literal conversion operator
operator bool
is represented as a convenience initializerBool(fromCxx:)
- Arithmetic operators, like
Functions and constructors that use r-value reference types are not yet available in Swift.
Swift supports calling some C++ function templates. Any function or
function template that uses a dependent type in its signature, or a universal
reference (T &&
) is not available in Swift. Any function template with
non-type template parameters is not available in Swift. Variadic function
templates are not available in Swift.
A C++ function whose return type is not supported in Swift, or with a parameter whose type is not supported in Swift is not available in Swift.
If a parameter of a C++ function has a default value, the parameter will also have a default value in Swift if:
- The function is not a constructor
- The parameter is not
inout
in Swift - The parameter is not a pointer
- The parameter is not a const reference
C++ Types Supported in Swift
The following C++ types can be used in Swift:
- Primitive types, like
int
andbool
- Pointers
- C++ references, excluding r-value reference / universal reference parameters
- Type aliases, only when the underlying type is supported in Swift
- Copyable structures and classes
- Movable non-copyable structures and classes
- Enumerations, including scoped enumerations (
enum class
)
C++ types that become value types in Swift can be constructed and passed around by value.
C++ types that become reference types can’t be constructed directly by Swift code. They can be passed around freely between Swift and C++.
C++ types defined inside of a C++ namespace
are available in
Swift.
Class and structure templates are not directly available in Swift. The instantiated specializations of a class or structure template are available in Swift. Swift code can access template specialization types by using a type alias defined in a C++ header.
Public data members of a C++ structure or class are available in Swift when the type of such data member is supported in Swift.
C++ Standard Library Types Supported in Swift
The following C++ standard library types are supported in Swift:
std::string
,std::u16string
,std::u32string
- Specializations of
std::pair
- Specializations of
std::vector
- Specializations of
std::map
andstd::unordered_map
- Specializations of
std::set
,std::multiset
andstd::unordered_set
- Specializations of
std::optional
- Specializations of
std::shared_ptr
- Specializations of
std::array
Other standard library types, like std::unique_ptr
, std::function
and
std::variant
are not yet supported in Swift.
Other C++ Features Handled by Swift
C++ Exceptions
Swift can interoperate with C++ code that throws exceptions. However, Swift does not support catching C++ exceptions. Instead, the running program terminates with a fatal error when a C++ exception that’s not caught by C++ code reaches Swift code.
Swift’s strict program termination enforcement for any uncaught exceptions is currently not supported when running Swift code built with Swift on Windows. Any mixed language program running on Windows should always terminate when a C++ exception propagates through Swift code as the program’s stack is unwound. Any attempt to recover from such uncaught exception can lead to undefined behavior in your program.
Clang’s Availability Attributes
C++ APIs annotated with Clang’s availability attributes receive the same availability annotation in Swift.
Supported Swift APIs
This section describes which Swift APIs get exposed to C++ in the generated header.
Swift Structures Supported by C++
Swift can generate C++ representation for most top-level Swift structures. The following Swift structures are not yet supported:
- Zero-sized structures that don’t have any stored properties
- Non-copyable structures
- Generic structures with generic constraints, or with more than three generic parameters, or that have variadic generics
Swift currently does not expose nested structures to C++.
Swift Classes and Actors Supported by C++
Swift can generate C++ representation for most top-level Swift classes and actors. The following Swift classes are not yet supported:
- Generic classes and actors
Swift currently does not expose nested classes and actors to C++.
Swift Enumerations Supported by C++
Swift can generate C++ representation for most top-level Swift enumerations that do not have associated values, and some top-level Swift enumerations that have associated values. The following Swift enumerations are not yet supported:
- Non-copyable enumerations
- Generic enumerations with generic constraints, or with more than three generic parameters, or that have variadic generics
- Enumerations that have an enumeration case with more than one associated value
- Indirect enumerations
Additionally, the types of all the associated values of an enumeration must be representable in C++. The exact set of representable types is described below, in the section that describes the representable parameter or return types.
Swift currently does not expose nested enumerations to C++.
Swift Functions and Properties Supported by C++
Any function, property, or initializer is exposed to C++ only when Swift can represent all of its parameter and return types in C++. A parameter or return type can be represented in C++ only when:
- it is a supported Swift structure / class / enumeration that is defined in the same Swift module.
- or, it is a C++ structure / class / enumeration that is not annotated as a reference type.
- or, it is one of the
supported Swift standard library types.
- if it’s a generic type, like
Array
, its generic parameters must be bound to one of the types listed here.
- if it’s a generic type, like
- or, it is an
UnsafePointer
/UnsafeMutablePointer
/Optional<UnsafePointer>
/Optional<UnsafeMutablePointer>
that points to any type from the supported three type categories listed above.
Functions or initializers that have a parameter type or a return type that’s not listed above cannot be represented in C++ yet. Properties of type that’s not listed above cannot be represented in C++ yet.
Additionally, the following Swift functions, properties and initializers can not yet be represented in C++:
- Asynchronous functions / properties
- Functions / properties / initializers that
throw
- Generic functions / properties / initializers with generic constraints or variadic generics
- Functions that return an opaque type
- Functions that return multiple values
- Functions / properties / initializers with the
@_alwaysEmitIntoClient
attribute
Supported Swift Standard Library Types
Swift is able to represent the following Swift standard library types in C++:
- Primitive types, such as
Bool
,Int
,Float
and their C variants likeCInt
- The full list of supported primitive types is provided below.
- Pointer types, like
OpaquePointer
,UnsafePointer
,UnsafeMutablePointer
,UnsafeRawPointer
andUnsafeMutableRawPointer
String
typeArray
typeOptional
type
For more details on using Swift types like String
in C++, check out
the section that describes how to
use Swift standard library types from C++.
Note that Swift tuples are not currently supported in C++.
List Of Primitive Swift Types Supported by C++
This table lists the primitive Swift types defined in Swift’s standard library that can be represented in C++:
Swift Type | Corresponding C++ type |
---|---|
Bool |
bool |
Int |
swift::Int |
UInt |
swift::UInt |
Int8 |
int8_t |
Int16 |
int16_t |
Int32 |
int32_t |
Int64 |
int64_t |
UInt8 |
uint8_t |
UInt16 |
uint16_t |
UInt32 |
uint32_t |
UInt64 |
uint64_t |
Float |
float |
Double |
double |
Float32 |
float |
Float64 |
double |
CBool |
bool |
CChar |
char |
CWideChar |
wchar_t |
CChar16 |
char16_t |
CChar32 |
char32_t |
CSignedChar |
signed char |
CShort |
short |
CInt |
int |
CLong |
long |
CLongLong |
long long |
CUnsignedChar |
unsigned char |
CUnsignedShort |
unsigned short |
CUnsignedInt |
unsigned int |
CUnsignedLong |
unsigned long |
CUnsignedLongLong |
unsigned long long |
CFloat |
float |
CDouble |
double |
Constraints and Limitations
Swift has some known limitations related to C++ interoperability support. They’re currently listed on GitHub.
Swift Package Manager Constraints
A Swift target that enables C++ interoperability in Swift Package Manager requires its dependencies to enable C++ interoperability as well. A Swift GitHub issue tracks the status of this constraint:
Performance Constraints
Swift’s current
support for C++ container types
does not provide explicit
performance guarantees. Most notably, Swift can make a deep copy of a
collection when it’s used in a for-in
loop in Swift.
The following issue tracks the status of this performance constraint:
Compatibility with Existing Codebases That Use C or Objective-C APIs in Swift
Enabling C++ interoperability in an existing codebase that imports and uses C or Objective-C APIs in Swift could cause some source breakages in Swift. Even though C++ is largely source compatible with C, there are several cases where C++ diverges. Some common cases of divergences that could cause Swift fail to import C or Objective-C headers in C++ mode are listed below:
- C++ uses a broader set of keywords that may conflict with existing C or
Objective-C APIs. For example, a C function one of whose parameters is
named
class
is not a valid C++ function. - Existing C or Objective-C headers might try to import another Clang module
inside of an
extern "C"
block. That’s not allowed in C++ mode.
In cases like this you’re advised to fix these issues in your C or Objective-C headers. If these headers come from a dependency that you don’t control, you should report an issue to the vendor that vends these headers.
Some existing codebases that use functions from the platform’s C standard library
could see ambiguity errors related to such functions being also defined in
the C++ standard library. Swift prefers to use math functions like sin
and pow
from the C standard library. Some other functions that
Swift doesn’t know about could still cause an error. In cases where
you see such an error related to an ambiguity of a function from the
platform’s C standard library you can resolve it by using an explicit module qualifier
from Swift when calling such function.