BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News C++26: Reflection, Memory Safety, Contracts, and a New Async Model

C++26: Reflection, Memory Safety, Contracts, and a New Async Model

Listen to this article -  0:00

The C++26 standard draft is now complete, reports Herb Sutter, long-time C++ expert and former chair of the ISO C++ standards committee. The finalized draft introduces reflection, enhances memory safety without requiring code rewrites, adds contracts with preconditions and postconditions alongside a new assertion statement, and establishes a unified framework for concurrency and parallelism.

Reflection is a mechanism that, as Sutter explains, gives developers the keys to C++ internal machinery, enabling the language to describe itself and generate code, and thus provide a solid foundation for metaprogramming. True to C++'s spirit, reflection comes with no runtime overhead. As a basic example of what reflection allows, the following code snippet shows how reflection enables a specialized syntax for declaring C++ interfaces:

class(interface) IFoo {
    int f();
    void g(std::string);
};

//-- will be translated into the "classical":

class IFoo {
    public:
      virtual int f() = 0;
      virtual void g(std::string) = 0;
      virtual ~IFoo() = default;
      IFoo() = default;
    protected:
      IFoo(IFoo const&) = default;
      void operator=(IFoo const&) = default;
};

Reflection can simplify C++’s future evolution by reducing the need for as many bespoke new language features, since many can now be expressed as reusable compile-time libraries—faster to design, easier to test, and portable from day one.

The interface abstraction is part of cppfront, a compiler that builds to pure ISO C++, which Sutter created to provide a faster way to experiment with proposals. It also includes abstractions like copyable for expressing a type with copy/move construction/assignment; ordered for defining a totally ordered type with operator<=>; union for a tagged union with names; regex, and more.

Another area where C++26 aims to deliver significant improvements is memory safety. This includes out-of-the-box elimination of undefined behavior when reading uninitialized local variables, as well as bounds safety for most standard library types, including vector, span, string, string_view. These changes have been already deployed in production at Apple and Google, Sutter says, across hundreds of millions of lines of C++ code:

This is no just-on-paper design. At Google alone, it has already fixed over 1,000 bugs, is projected to prevent 1,000 to 2,000 bugs a year, and has reduced the segfault rate across the production fleet by 30%.

Even more significantly, these benefits where achieved simply by recompiling existing code with the new compiler. In only seven cases was the compiler unable to analyze highly optimized code, requiring developers to use a fine-grained API to selectively opt out of memory safety in those specific parts.

C++26 contracts bring defensive programming into the language, improving both functional and memory safety. They allow developers to express pre- and post-conditions that must not be violated across a method execution. Contracts allow to move assertions into function declarations making them visible to callers and static analysis tools. C++ offers four ways to handle contract violations: ignore, observe, enforce, and quick enforce. In addition, they bring a native assertion mechanism that replaces C's assert macro.

Finally, C++26 introduces std::execution as a framework to express and control concurrency and parallelism. The three main abstractions in the framework are schedulers, senders, and receivers, which can be composed through a set of customizable asynchronous algorithms. std::execution is designed to work nicely with C++20 coroutines and makes it easier to "write programs that use structured (rigorously lifetime-nested) concurrency and parallelism to be data-race-free by construction".

The two major C++ compilers, GCC and Clang, have already implemented most of C++26 features during the standardization process and these features will soon make their way into mainline releases.

About the Author

Rate this Article

Adoption
Style

BT