Digiprogrammer

Category: Software Programming

Posted on: April 7, 2025

What is C++23 and Its New Features?

C++23 introduces key features like contracts, improved memory safety, and enhanced concurrency, optimizing performance while maintaining compatibility.

C++23, the most recent iteration of the C++ programming language, is a powerhouse of modern features and enhancements. With its roots in 1985, C++ has always been a language of choice for high-performance applications, and the updates in C++23 only serve to cement its position in areas such as system programming, game development, scientific computing, and more. This post explores the new features in C++23, how they solve real-world problems, the challenges faced by developers, and how some of the most popular libraries and frameworks have adopted these advancements.

The Key Features of C++23

C++23, while building upon the features of C++20, introduces a suite of new features and updates that provide better functionality, enhanced safety, and increased performance for developers. These features cover a wide range of areas, including memory management, concurrency, type safety, debugging, and more.

1. The <mdspan> Library for Multidimensional Arrays

In C++23, the <mdspan> library provides a standardized approach to managing multidimensional arrays, solving many of the inefficiencies in how previous C++ versions handled multi-dimensional data. This feature is particularly useful in fields like scientific computing, where high-performance and scalable handling of large datasets are crucial.

By using <mdspan>, developers can access arrays with improved indexing and layout flexibility. The main advantage is that this library abstracts the complexities of memory layouts while providing low-level control that is still highly efficient.

Real-World Applications:

  • TensorFlow can use <mdspan> for enhanced handling of tensors, simplifying the manipulation of multidimensional data.
  • Eigen (a C++ template library for linear algebra) will benefit from this by optimizing matrix operations, improving performance for scientific computations.
  • Kokkos, a performance portability library, can leverage <mdspan> for easier multidimensional data management in parallel and distributed computing.

2. Stack Trace Support

One of the biggest improvements in C++23 is the built-in stack trace functionality. Before this, developers had to rely on external libraries to capture and present stack traces. C++23 standardizes this feature, making debugging easier by automatically generating detailed stack traces when exceptions are thrown.

This feature is essential in identifying the root cause of errors in complex applications, especially in large-scale systems, where pinpointing bugs manually is time-consuming and error-prone.

Real-World Applications:

  • Google’s gRPC: By utilizing the stack trace functionality, Google’s gRPC library can now more efficiently handle errors in distributed systems, reducing the time needed for debugging.
  • Microsoft’s C++ REST SDK (cpprestsdk): Offers more informative error reports when dealing with complex network-related operations, improving developers' ability to diagnose issues faster.

3. Enhanced std::format for Type-Safe String Formatting

The std::format function introduced in C++20 revolutionized string formatting in C++ by offering a safe, modern, and powerful alternative to the old printf method. C++23 expands this functionality, enabling more advanced and efficient formatting scenarios. The new std::format provides better error handling, more type safety, and can handle more complex formatting cases with ease.

By using std::format, developers can format strings without worrying about mismatched types, a common problem in C++20’s printf-style formatting.

Real-World Applications:

  • fmtlib: A powerful C++ formatting library, fmtlib enhances logging and string manipulation. Libraries such as spdlog (a fast C++ logging library) can now use the new features to produce clearer and more efficient logging output.
  • ImGui: The popular graphical user interface library can also benefit from C++23’s std::format for rendering UI elements dynamically with better type safety and performance.

4. Enhanced std::ranges for Functional Programming

C++20 introduced the std::ranges library, which brought functional-style programming to C++ with sequences and iterators. C++23 improves on this, adding new algorithms and enhancing existing ones. These enhancements make it easier for developers to work with data sequences in a declarative manner.

By utilizing std::ranges, C++23 allows developers to write more expressive, efficient, and easier-to-understand code, especially when working with large data sets or performing complex operations on collections.

Real-World Applications:

  • Range-V3: The Range-V3 library, which influenced std::ranges, can now fully utilize the new features in C++23. This makes it possible to implement even more advanced data manipulations and algorithms with less code and fewer bugs.
  • Boost.Hana: Boost.Hana, a metaprogramming library for C++, can integrate C++23's enhanced std::ranges for compile-time programming tasks. This allows developers to perform even more powerful operations at compile time, resulting in faster and more optimized code.

5. Contracts for Safer Code

C++23 expands on the contract programming feature, which was introduced experimentally in C++20. Contracts allow developers to specify preconditions, postconditions, and assertions directly in the code. This provides a way to check and enforce rules for code correctness during both compile-time and runtime, leading to safer, more predictable programs.

Contracts help prevent a wide range of potential errors, including logical mistakes and undefined behaviors, by making explicit the assumptions and conditions under which the code operates.

Real-World Applications:

  • LLVM: The LLVM compiler infrastructure can now adopt C++23’s contract-based programming to ensure stricter code guarantees, reducing the likelihood of runtime errors.
  • C++ Core Guidelines: These guidelines can be strengthened by using C++23’s contracts to enforce best practices and ensure robust and reliable code across C++ projects.

6. std::expected for Better Error Handling Without Exceptions

The introduction of std::expected in C++23 provides a more performance-friendly alternative to exceptions. This feature enables developers to handle errors without the overhead of exception handling, providing a more predictable way of reporting errors.

std::expected is a way of either returning a value or an error, allowing code to express failure explicitly while avoiding the costly process of throwing and catching exceptions. This is particularly important in performance-critical applications.

Real-World Applications:

  • Tesla Firmware: Tesla's firmware development team uses std::expected for error handling in embedded systems, where performance and reliability are paramount.
  • Libc++: The C++ standard library implementation, libc++, can integrate std::expected to enhance error handling, especially in performance-sensitive components of the library.

7. Improved Coroutines for Asynchronous Programming

C++20 introduced coroutines, and C++23 improves their usability and performance. Coroutines allow for asynchronous programming that looks synchronous, simplifying the handling of tasks such as I/O operations, network requests, or concurrent tasks.

The enhancements in C++23 make coroutines easier to use, more efficient, and more reliable, enabling developers to write asynchronous code that behaves like normal, linear code.

Real-World Applications:

  • Facebook’s Folly: Facebook’s Folly library for asynchronous programming benefits from the enhanced coroutines in C++23, especially for handling millions of network requests per second with minimal overhead.
  • Microsoft’s C++ Concurrency Runtime: C++23’s coroutine improvements allow for more efficient scheduling and execution of concurrent tasks, making it easier to build high-performance, multithreaded applications.

8. Pattern Matching (Proposed for Future Versions)

While still a work-in-progress, C++23 introduces the groundwork for pattern matching—a feature that has been widely adopted by other languages like Python and Rust. Pattern matching allows developers to match complex data structures with cleaner, more readable syntax.

Though not yet fully implemented in C++23, this feature is expected to evolve significantly in future C++ releases and is a crucial addition for writing modern, concise, and efficient code.

9. Reflection (Proposed for Future Versions)

Another anticipated feature in C++ is Reflection, which would allow developers to inspect and modify types, classes, and objects at runtime. This is a significant improvement for metaprogramming and generic programming, providing greater flexibility and control.

Practical Applications of C++23 Features in Modern Libraries

C++23 introduces an array of features that have a direct impact on industries that require high-performance computing. From game engines to financial systems and embedded devices, the new features enhance the flexibility, safety, and efficiency of C++ for these applications. Let’s dive into each sector, providing detailed technical information about how C++23’s updates are transforming real-world applications.

1. Game Development: Improving Performance and Scalability

C++ has long been the backbone of game development, with its high performance being a critical factor in demanding environments like video games. The new features in C++23 improve game code efficiency, making use of advancements in memory management, concurrency, and error-handling mechanisms. Let’s explore how these updates enhance game development.

Memory Management with std::expected and Smart Pointers:

C++23’s introduction of std::expected and continued improvements to smart pointers (like std::unique_ptr and std::shared_ptr) provides developers with more robust and safer error handling. In game engines, performance-critical applications often require managing memory explicitly to ensure smooth gameplay. std::expected allows for error handling without resorting to exceptions, reducing runtime overhead. This is critical for game engines, which require minimal latency.

For example, in Unreal Engine, which processes millions of physics calculations per second, leveraging C++23’s memory management and concurrency features helps optimize the interaction between physics engines and AI processing. The reduction in overhead from improved error handling results in smoother frame rates and better resource management.

Concurrency and Coroutines in Game Engines:

Concurrency plays a significant role in game engines, particularly when dealing with the complex and often parallel computations in physics simulations, AI, and rendering pipelines. C++23’s coroutines significantly improve asynchronous programming, allowing game developers to write code that runs asynchronously while appearing synchronous. This leads to more readable code and improves the overall performance.

An example of this can be seen in the Unity engine, which has implemented C++23-style coroutines in their background task management. With coroutines, Unity’s engine can handle thousands of asynchronous tasks concurrently without the typical issues of thread management, resulting in better performance when rendering complex scenes or handling large-scale multiplayer interactions.

2. Financial Systems: Ultra-Low-Latency Performance

In the high-frequency trading (HFT) industry, microseconds can make a huge difference, and C++ is the language of choice because of its low-latency capabilities. C++23’s improvements enable even more efficient real-time computation and error handling, ensuring that financial systems operate at the highest performance levels.

Concurrency and Low-Latency Improvements in C++23:

C++23’s advancements in multithreading, particularly in improving concurrency and reducing contention, make the language more suited for high-frequency trading algorithms. Libraries like QuantLib, which provide quantitative finance tools, can now leverage these new features to enhance the performance of complex financial models, including risk assessments and pricing models.

A significant update in C++23 for financial systems is the introduction of std::expected, which provides a way to handle errors in financial algorithms without the overhead of exceptions. Financial systems often require quick decisions, and catching an exception can result in significant performance degradation. By using std::expected, trading systems can avoid unnecessary runtime penalties by explicitly defining failure states, resulting in faster execution times and lower latencies for financial transactions.

Real-Time Computing in C++23:

Financial systems also rely heavily on real-time data feeds for executing trades. C++23’s improvements in error-handling mechanisms, combined with better memory safety, improve the robustness of systems such as algorithmic trading platforms. These systems need to handle large volumes of real-time data, and even a slight delay in processing could lead to a loss of competitive advantage.

An example of how C++23 improves this is C++’s real-time operating system (RTOS) implementations, such as VxWorks. With the introduction of more advanced concurrency management and memory handling features, the C++23 standard has become more compatible with high-frequency trading systems requiring precise timing and extremely low-latency execution.

3. Embedded Systems and IoT: Enhancing Safety and Reliability

C++ has long been favored in embedded systems for its ability to control hardware at a low level while maintaining high performance. C++23 further strengthens its position by introducing features that enhance memory safety and code correctness, which is critical in environments such as automotive, medical devices, and IoT (Internet of Things).

Memory Safety and Contracts in Automotive Software:

C++23's introduction of contracts (preconditions, postconditions, and assertions) provides developers with a formal way of defining safe programming practices. This is particularly useful in embedded systems, where safety and reliability are non-negotiable. For example, in automotive software development, where safety-critical systems like autonomous driving or collision detection must operate correctly, contracts help prevent common errors such as null pointer dereferencing and buffer overflows.

Embedded Systems and Real-Time Requirements:

In embedded systems, the efficiency of memory and resource usage is paramount. By leveraging C++23’s std::expected, developers in fields like medical devices or industrial automation can manage errors more effectively without relying on exceptions, which can be too costly in real-time environments. Systems like VxWorks or FreeRTOS (both widely used in embedded systems) can now adopt these new features for better performance in environments where low-latency and resource conservation are essential.

In the IoT space, C++23’s memory management enhancements enable more effective handling of constrained hardware environments, such as low-power devices with limited processing capabilities. These systems often need to execute tasks with minimal memory, and C++23’s improvements in error handling, concurrency, and resource management ensure that they remain efficient and reliable even with demanding applications like smart home systems, wearables, and industrial sensors.

Challenges with C++23 Adoption in Modern Development

While C++23 introduces several advancements, the adoption of these features isn't without its challenges. Developers face hurdles with backward compatibility, legacy systems, and the steep learning curve associated with complex language features like contracts and template metaprogramming. Let's address some of the primary challenges developers may encounter when transitioning to C++23.

Legacy Codebases and Compiler Support:

Older C++ codebases that have been built over several years or even decades may not immediately take advantage of C++23’s new features. Migrating legacy systems to take full advantage of modern features like contracts or coroutines can require significant refactoring. Furthermore, while major compilers such as GCC, Clang, and MSVC are progressively supporting C++23, some features may still be under development or not yet fully optimized, requiring additional testing and fine-tuning.

Complexity of New Features:

The complexity of new features, particularly contract-based programming, presents a learning curve for many developers. Writing contracts requires a deep understanding of the underlying system and its invariants, which can make implementation difficult for those unfamiliar with formal verification techniques. Similarly, template metaprogramming in C++ remains an advanced topic, and while C++23 simplifies some of the associated pain points, understanding and using it effectively still requires a high level of expertise.

Backward Compatibility

C++23, like its predecessors, is designed to maintain a high level of backward compatibility with previous versions of C++. However, it introduces some changes that may have a slight impact on existing codebases. While C++23 does not "remove" major features or introduce drastic incompatibilities, it does bring a few modifications that could affect how certain things behave. Here's a breakdown:

Deprecation and Removal of Certain Features:

  • std::ranges::iota with std::view: In some implementations, certain aspects of the ranges library, like iota views, have been refined or adjusted to align better with the overall design of the ranges framework. While not necessarily removed, some existing implementations may require modifications.
  • std::move on Const References: C++23 introduces stricter guidelines on using std::move with constant references, making it less forgiving in certain contexts. This could impact developers who have used std::move with const references incorrectly, though it’s an edge case.

Potential for Compiler Warnings and Errors Due to New Features:

  • Contracts and Pre/Postconditions: The new contract-based programming feature allows developers to define explicit preconditions, postconditions, and assertions. If these contracts are not well-defined in existing code, compilers may emit warnings or errors. This introduces a new level of compile-time validation that can break existing code if contracts are violated.
  • Changes in the Behavior of constexpr Functions: There are some tighter restrictions on what is allowed in constexpr functions in C++23, which could potentially cause issues for code that used constexpr in ways that C++23 now disallows.

Changes in Deprecated Features or Best Practices:

  • Memory Management Features: The introduction of new memory management features like std::expected and enhancements to smart pointers (e.g., std::out_ptr in C++23) may make older memory management practices (like manual malloc/free calls) feel outdated or suboptimal. Some older libraries that rely heavily on manual memory management may need refactoring to adapt to the more modern, safer memory handling paradigms encouraged by C++23.

Increased Standardization of Previously Platform-Specific Features:

  • Multithreading and Concurrency Features: C++23 brings more robust multithreading and concurrency capabilities, including improved atomic operations and thread synchronization tools. For older codebases that heavily rely on platform-specific threading libraries, these new standard features could lead to incompatibility if the code is not updated to use the new features properly.

The impact

For the most part, C++23 is designed with backward compatibility in mind, meaning that existing codebases will generally continue to work without major changes. However, developers need to be mindful of the new features and their implications for existing code:

  • Warning on Deprecated or Obsolete Features: While C++23 doesn’t remove any features outright, it introduces some features that might warn against older, unsafe practices or deprecated methods.
  • Use of Modern Features May Require Code Refactoring: Libraries or applications that heavily rely on older patterns or are built on older standards of C++ may require adjustments to make use of new, more efficient methods for error handling (like std::expected) or memory safety features.

The Ongoing Evolution of C++23

C++23 ushers in a new era for one of the most powerful and widely used programming languages, making it even more relevant for modern computing needs. By enhancing memory safety, error handling, concurrency, and providing modern tools for real-time and embedded systems, C++23 enables developers to write safer, more efficient, and scalable software.

The language’s new features pave the way for better performance across a range of industries, from game development to financial systems and embedded IoT applications. As more libraries and frameworks adopt these new features, the ability of C++ to power high-performance applications will only grow.

While the challenges of adopting C++23 are not insignificant, particularly for those working with legacy code, the rewards of making the switch are clear. By embracing C++23’s advances, developers can leverage the full power of C++ to build tomorrow’s software, faster and more efficiently than ever before.