This document is an initial, partially reviewed draft
This table shows how well C++ standard library overloads can be represented in Rust.
These outcomes are based on the current state of the experimental splat compiler feature and
overloading macro: they are not Rust language design decisions.
See the Limitations section below the table for more details.
Key:
⛔ Conflicting Overloads
🦀 Rust Compiler Limitations
⚙️ Overload Macro Limitations
🌗 Partial Support or Poor Ergonomics
✅ Works in Rust
? Needs Analysis
blank No C++ Overloads
| C++ Standard Library Class | Constructors | Accessors | Modifiers | Transforms |
|---|---|---|---|---|
| Free Functions | Constructors | Accessors | Modifiers | Transforms |
| TODO | ? | ? | ? | |
| Non-Template Classes | Constructors | Accessors | Modifiers | Transforms |
| TODO | ? | ? | ? | ? |
| Template Classes | Constructors | Accessors | Modifiers | Transforms |
| forward_list | ✅ | 🌗⚙️1 | 🌗⚙️?2 | ✅ |
| TODO | ? | ? | ? | ? |
Constructors: Create an instance of the class, called as Class::Class(...)
Accessors: Get information about the class, called as instance->get(...)
Modifiers: Add or change the items in a list class, called as instance->put(...)
Transforms: Rearrange the items in a list class, called as instance->sort(...)
This section summarises common issues discovered during the analysis, and documents less interesting overloads that were skipped.
Overload macro missing functionality:
- methods that only differ by
selftype, for exampleget(&self) -> &Tandget(&mut self) -> &mut T- this can be worked around using associated functions, but the ergonomics suffer
- Generic types:
- this makes representing C++ templated types with generic Rust types impossible
- doesn't support
impl Iteratororwhere I: Iteratoras arguments, but supports&dyn Iterator(which is less ergonomic)
- Lifetimes:
- generic lifetimes aren't supported
- when the input method has elided lifetimes, the generated code doesn't add lifetimes where needed
Some overloads are confusing or hard to use, so we might not want to represent them in Rust:
get(&self) -> &Tandget(&mut self) -> &mut Tis a subtle difference, typical Rust APIs usegetandget_mutinstead- in generic list overloads,
new(count: usize)andnew(item: T)are easily confused ifTis an integer (and they conflict ifTisusize, which means it can't be fully generic)- this can be resolved by skipping overloads for initializer lists
&dyn Iteratoroverloads require a type cast- this could be resolved with improvements to the macro, or with an iterator adapter type
Type inference doesn't work on some overloads: this is likely a macro or compiler experiment limitation.
Some C++ overloads use a tag argument for overload disambiguation, a strategy which could be adopted in Rust APIs. But in some cases, the Rust overload might not need disambiguation.
Some overloads have been ignored or minimised in this analysis.
These overloads are less interesting:
- overloaded operators: already available in stable Rust
- overloads with an allocator argument, or that only differ by noexcept: not an interesting difference
- overloads that only differ by
const/non-const,&/&&(lvalue/rvalue) in C++, or&/&mutin Rust
These overloads have no equivalent in Rust:
- assignment functions, assignment operators, and
swap: there is no "type move method" in Rust (it usesmemcpyfor assignment/swaps) - legacy iterator pointer-like methods for various positions (
before_begin/begin/end) - initializer list methods: these are also a common source of overload conflicts for C++ templated lists
When the same overloaded functions are available on different classes, we only analyse the overload on one of those classes.
When one overloaded function takes the same argument sets (or a subset of the argument set) of
another overloaded function, we only analyse one of the argument sets. For example,
unique()/unique(predicate) and sort()/sort(predicate).
In some cases, we focus on the most "difficult" overload in a category, and skip the rest.