| # C++23 language changes |
| |
| ## Breaking changes |
| |
| ### Many transitive includes have been removed |
| |
| In C++23, libc++ dropped a bunch of transitive includes, so a lot of includes |
| you were getting by accident now need to be explicitly included. Most popular |
| ones seem to be `<algorithm>`, `<memory>`, `<mutex>`, and `<vector>`. |
| |
| Fix: Add missing includes. You can reference [cppreference.com](https://cppreference.com/) |
| for the includes of any function, type, or symbol. |
| |
| ### `std::unique_ptr`'s destructor became `constexpr` |
| |
| In C++23, `std::unique_ptr`'s destructor became `constexpr`. As a result, |
| `std::unique_ptr<T>` has started to complain in more cases that `sizeof(T)` |
| is invalid when T is an incomplete type. |
| |
| Fix: Ensure a type (`T`) is completely defined before it is used in unique_ptr, |
| typically by moving the definition of the type (`T`) before its use. In certain |
| cases, it might be hard to move the definition so you can move the destructor of |
| the class containing the `unique_ptr<T>` after the definition of type (`T`). |
| |
| ### `std::string` does not allow nullptr anymore |
| |
| In C++23, `std::string` removed the constructor that accepted `nullptr`. You |
| can no longer assign `nullptr` to a `std::string` or return `nullptr` for a |
| fuction with return type of `std::string`. These actions now trigger a |
| compile-time error, preventing the runtime crashes that occurred in previous |
| versions. |
| |
| Fix: Change your nullptr to "". |
| |
| ### `-Wfortify-source` with C++23 is more precise |
| |
| Fortify performs safety checks at compile-time whenever possible, falling back to |
| runtime only when necessary. With C++23's increased use of `constexpr`, Fortify |
| can verify more conditions during compilation. This shifts some errors from |
| runtime to compile-time, potentially causing build failures in code now provably |
| known to be unsafe. |
| |
| Fix: Look at the compile-time warnings and make the fix such that the size fits the |
| destination. |
| |
| ### Libc++ removed `__resize_default_init` for `resize_and_overwrite` |
| |
| Libc++ removed [`__resize_default_init`](https://github.com/llvm/llvm-project/pull/157121) |
| recently because it was an internal API used only in a specific case. They decided to move |
| to the public one, `resize_and_overwrite`, that became available since C++23. |
| |
| Fix: Replace all your uses of `__resize_default_init` with `resize_and_overwrite` for C++23. |
| |
| ## Non-Breaking changes |
| |
| ### Range-based For Loop issue was fixed |
| |
| Since C++11, the range-based for loop had undefined behavior for specific cases because |
| they would result in dangling references. C++23 fixed this issue by extending the |
| lifetime of all temporaries in the range expression to the end of the loop. You can |
| find more information and examples in the design paper |
| [P2644R1](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2644r1.pdf). |
| |
| ## Other Changes |
| |
| You can find the other new C++23 language features at |
| [https://en.cppreference.com/w/cpp/23.html](https://en.cppreference.com/w/cpp/23.html) |