Skip to main content
Redhat Developers  Logo
  • Products

    Featured

    • Red Hat Enterprise Linux
      Red Hat Enterprise Linux Icon
    • Red Hat OpenShift AI
      Red Hat OpenShift AI
    • Red Hat Enterprise Linux AI
      Linux icon inside of a brain
    • Image mode for Red Hat Enterprise Linux
      RHEL image mode
    • Red Hat OpenShift
      Openshift icon
    • Red Hat Ansible Automation Platform
      Ansible icon
    • Red Hat Developer Hub
      Developer Hub
    • View All Red Hat Products
    • Linux

      • Red Hat Enterprise Linux
      • Image mode for Red Hat Enterprise Linux
      • Red Hat Universal Base Images (UBI)
    • Java runtimes & frameworks

      • JBoss Enterprise Application Platform
      • Red Hat build of OpenJDK
    • Kubernetes

      • Red Hat OpenShift
      • Microsoft Azure Red Hat OpenShift
      • Red Hat OpenShift Virtualization
      • Red Hat OpenShift Lightspeed
    • Integration & App Connectivity

      • Red Hat Build of Apache Camel
      • Red Hat Service Interconnect
      • Red Hat Connectivity Link
    • AI/ML

      • Red Hat OpenShift AI
      • Red Hat Enterprise Linux AI
    • Automation

      • Red Hat Ansible Automation Platform
      • Red Hat Ansible Lightspeed
    • Developer tools

      • Red Hat Trusted Software Supply Chain
      • Podman Desktop
      • Red Hat OpenShift Dev Spaces
    • Developer Sandbox

      Developer Sandbox
      Try Red Hat products and technologies without setup or configuration fees for 30 days with this shared Openshift and Kubernetes cluster.
    • Try at no cost
  • Technologies

    Featured

    • AI/ML
      AI/ML Icon
    • Linux
      Linux Icon
    • Kubernetes
      Cloud icon
    • Automation
      Automation Icon showing arrows moving in a circle around a gear
    • View All Technologies
    • Programming Languages & Frameworks

      • Java
      • Python
      • JavaScript
    • System Design & Architecture

      • Red Hat architecture and design patterns
      • Microservices
      • Event-Driven Architecture
      • Databases
    • Developer Productivity

      • Developer productivity
      • Developer Tools
      • GitOps
    • Secure Development & Architectures

      • Security
      • Secure coding
    • Platform Engineering

      • DevOps
      • DevSecOps
      • Ansible automation for applications and services
    • Automated Data Processing

      • AI/ML
      • Data Science
      • Apache Kafka on Kubernetes
      • View All Technologies
    • Start exploring in the Developer Sandbox for free

      sandbox graphic
      Try Red Hat's products and technologies without setup or configuration.
    • Try at no cost
  • Learn

    Featured

    • Kubernetes & Cloud Native
      Openshift icon
    • Linux
      Rhel icon
    • Automation
      Ansible cloud icon
    • Java
      Java icon
    • AI/ML
      AI/ML Icon
    • View All Learning Resources

    E-Books

    • GitOps Cookbook
    • Podman in Action
    • Kubernetes Operators
    • The Path to GitOps
    • View All E-books

    Cheat Sheets

    • Linux Commands
    • Bash Commands
    • Git
    • systemd Commands
    • View All Cheat Sheets

    Documentation

    • API Catalog
    • Product Documentation
    • Legacy Documentation
    • Red Hat Learning

      Learning image
      Boost your technical skills to expert-level with the help of interactive lessons offered by various Red Hat Learning programs.
    • Explore Red Hat Learning
  • Developer Sandbox

    Developer Sandbox

    • Access Red Hat’s products and technologies without setup or configuration, and start developing quicker than ever before with our new, no-cost sandbox environments.
    • Explore Developer Sandbox

    Featured Developer Sandbox activities

    • Get started with your Developer Sandbox
    • OpenShift virtualization and application modernization using the Developer Sandbox
    • Explore all Developer Sandbox activities

    Ready to start developing apps?

    • Try at no cost
  • Blog
  • Events
  • Videos

New C++ features in GCC 10

 

September 24, 2020
Marek Polacek
Related topics:
LinuxOpen source
Related products:
Developer Tools

Share:

    The GNU Compiler Collection (GCC) 10.1 was released in May 2020. Like every other GCC release, this version brought many additions, improvements, bug fixes, and new features. Fedora 32 already ships GCC 10 as the system compiler, but it's also possible to try GCC 10 on other platforms (see godbolt.org, for example). Red Hat Enterprise Linux (RHEL) users will get GCC 10 in the Red Hat Developer Toolset (RHEL 7), or the Red Hat GCC Toolset (RHEL 8).

    This article focuses on the part of the GCC compiler on which I spend most of my time: The C++ front end. My goal is to present new features that might be of interest to C++ application programmers. Note that I do not discuss developments in the C++ language itself, although some language updates overlap with compiler updates. I also do not discuss changes in the standard C++ library that comes with GCC 10.

    We implemented many C++20 proposals in GCC 10. For the sake of brevity, I won't describe them in great detail. The default dialect in GCC 10 is -std=gnu++14; to enable C++20 features, use the -std=c++20 or -std=gnu++20 command-line option. (Note that the latter option allows GNU extensions.)

    C++ concepts

    While previous versions of GCC (GCC 6 was the first) had initial implementations of C++ concepts, GCC 10 updated concepts to conform to the C++20 specification. This update also improved compile times. Subsequent patches have improved concepts-related diagnostics.

    In C++ template parameters, typename means any type. But most templates must be constrained in some way; as an example, you want to only accept types that have certain properties, not just any type. Failing to use the correct type often results in awful and verbose error messages. In C++20, you can constrain a type by using a concept, which is a compile-time predicate that specifies the set of operations that can be applied to the type. Using GCC 10, you can define your own concept (or use one defined in <concepts>):

    #include <type_traits>
    // Require that T be an integral type.
    template<typename T> concept C = std::is_integral_v<T>;
    

    And then use it like this:

    template<C T> void f(T) { }
    void g ()
    {
      f (1); // OK
      f (1.2); // error: use of function with unsatisfied constraints
    }
    

    Starting with GCC 10, the C++ compiler also supports constrained auto. Using our concept above, you can now write:

    int fn1 ();
    double fn2 ();
    
    void h ()
    {
      C auto x1 = fn1 (); // OK
      C auto x2 = fn2 (); // error: deduced initializer does not satisfy placeholder constraints
    }

    Coroutines

    GCC 10 supports stackless functions that can be suspended and resumed later without losing their state. This feature lets us execute sequential code asynchronously. It requires the -fcoroutines command-line option.

    Unevaluated inline-assembly in constexpr functions

    Code like this now compiles:

    constexpr int
    foo (int a, int b)
    {
      if (std::is_constant_evaluated ())
        return a + b;
      // Not in a constexpr context.
      asm ("/* assembly */");
      return a;
    }

    See the proposal for details.

    Comma expression in array subscript expressions

    This type of expression is now deprecated, so GCC 10 warns for code like this:

    int f (int arr[], int a, int b)
    {
      return arr[a, b];
    }
    

    Only a top-level comma is deprecated, however, so arr[(a, b)] compiles without a warning.

    Structured bindings

    GCC 10 improves and extends structured bindings. For instance, it's now possible to mark them static:

    struct S { int a, b, c; } s;
    static auto [ x, y, z ] = s;
    

    This example doesn't compile with GCC 9, but it compiles with GCC 10.

    The constinit keyword

    GCC 10 uses the C++20 specifier constinit to ensure that a (static storage duration) variable is initialized by a constant initializer.

    This might alleviate problems with the static initialization order fiasco. However, the variable is not constant: It is possible to modify it after initialization has taken place. Consider:

    constexpr int fn1 () { return 42; }
    int fn2 () { return -1; }
    constinit int i1 = fn1 (); // OK
    constinit int i2 = fn2 (); // error: constinit variable does not have a constant initializer
    

    GCC doesn't support Clang's require_constant_initialization attribute, so you can use __constinit in earlier C++ modes, as an extension, to get a similar effect.

    Deprecated uses of volatile

    Expressions that involve both loads and stores of a volatile lvalue, such as ++ or +=, are deprecated. The volatile-qualified parameter and return types are also deprecated, so GCC 10 will warn in:

    void fn ()
    {
      volatile int v = 42;
      // Load + store or just a load?
      ++v; // warning: deprecated
    }
    

    Conversions to arrays of unknown bound

    Converting to an array of unknown bound is now permitted, so the following code compiles:

    void f(int(&)[]);
    int arr[1];
    void g() { f(arr); }
    int(&r)[] = arr;
    

    Note: Conversion in the other direction—from arrays of unknown bound—currently is not allowed by the C++ standard.

    constexpr new

    This feature allows dynamic memory allocation at compile time in a constexpr context:

    constexpr auto fn ()
    {
      int *p = new int{10};
      // ... use p ...
      delete p;
      return 0;
    }
    
    int main ()
    {
      constexpr auto i = fn ();
    }
    

    Note that the storage allocated at compile time in a constexpr context must also be freed at compile time. And, given that constexpr doesn't allow undefined behavior, use-after-free is a compile-time error. The new expression also can't throw. This feature paves the way for constexpr standard containers such as <vector> and <string>.

    The [[nodiscard]] attribute

    The [[nodiscard]] attribute now supports an optional argument, like so:

    [[nodiscard("unsafe")]] int *fn ();
    

    See the proposal for details.

    CTAD extensions

    C++20 class template argument deduction (CTAD) now works for alias templates and aggregates, too:

    template <typename T>
    struct Aggr { T x; };
    Aggr a = { 1 }; // works in GCC 10
    
    template <typename T>
    struct NonAggr { NonAggr(); T x; };
    NonAggr n = { 1 }; // error: deduction fails
    

    Parenthesized initialization of aggregates

    You can now initialize an aggregate using a parenthesized list of values such as (1, 2, 3). The behavior is similar to {1, 2, 3}, but in parenthesized initialization, the following exceptions apply:

    • Narrowing conversions are permitted.
    • Designators (things like .a = 10) are not permitted.
    • A temporary object bound to a reference does not have its lifetime extended.
    • There is no brace elision.

    Here's an example:

    struct A { int a, b; };
    A a1{1, 2};
    A a2(1, 2); // OK in GCC 10 -std=c++20
    auto a3 = new A(1, 2); // OK in GCC 10 -std=c++20
    

    Trivial default initialization in constexpr contexts

    This usage is now allowed in C++20. As a result, a constexpr constructor doesn't necessarily have to initialize all the fields (but reading an uninitialized object is, of course, still forbidden):

    struct S {
      int i;
      int u;
      constexpr S() : i{1} { }
    };
    
    constexpr S s; // error: refers to an incompletely initialized variable
    S s2; // OK
    
    constexpr int fn (int n)
    {
      int a;
      a = 5;
      return a + n;
    }
    

    constexpr dynamic_cast

    In constexpr contexts, you can now evaluate a dynamic_cast at compile time. Virtual function calls in constant expressions were already permitted, so this proposal made it valid to use a constexpr dynamic_cast, like this:

    struct B { virtual void baz () {} };
    struct D : B { };
    constexpr D d;
    constexpr B *b = const_cast<D*>(&d);
    static_assert(dynamic_cast<D*>(b) == &d);
    

    Previously, a constexpr dynamic_cast would have required a runtime call to a function defined by the C++ runtime library. Similarly, a polymorphic typeid is now also allowed in constexpr contexts.

    Note: C++20 modules are not supported in GCC 10; they are still a work in progress (here is a related proposal). We hope to include them in GCC 11.

    Additional updates

    In non-C++20 news, the C++ compiler now detects modifying constant objects in constexpr evaluation, which is undefined behavior:

    constexpr int
    fn ()
    {
      const int i = 5;
      const_cast<int &>(i) = 10; // error: modifying a const object
      return i;
    }
    constexpr int i = fn ();
    

    GCC also handles the case when a constant object under construction is being modified and doesn't emit an error in that case.

    Narrowing conversions

    Narrowing conversions are invalid in certain contexts, such as list initialization:

    int i{1.2};
    

    GCC 10 is able to detect narrowing in more contexts where it's invalid, for instance, case values in a switch statement:

    void g(int i)
    {
      switch (i)
      case __INT_MAX__ + 1u:;
    }
    

    The noexcept specifier

    GCC 10 properly treats the noexcept specifier as a complete-class context. As with member function bodies, default arguments, and non-static data member initializers, you can declare names used in a member function's noexcept specifier later in the class body. The following valid C++ code could not be compiled with GCC 9, but it compiles with GCC 10:

    struct S {
      void foo() noexcept(b);
      static constexpr auto b = true;
    };
    

    The deprecated attribute

    You can now use the deprecated attribute on namespaces:

    namespace v0 [[deprecated("oh no")]] { int fn (); }
    
    void g ()
    {
      int x = v0::fn (); // warning: v0 is deprecated
    }
    

    GCC 9 compiles this code but ignores the attribute, whereas GCC 10 correctly warns about using entities from the deprecated namespace.

    Defect report resolutions

    We resolved several defect reports (DRs) in GCC 10. One example is DR 1710, which says that when we are naming a type, the template keyword is optional. Therefore, the following test compiles without errors with GCC 10:

    template<typename T> struct S {
      void fn(typename T::template B<int>::template C<int>);
      void fn2(typename T::B<int>::template C<int>);
      void fn3(typename T::template B<int>::C<int>);
      void fn4(typename T::B<int>::C<int>);
    };
    

    Another interesting DR is DR 1307, which clarified how overload resolution ought to behave when it comes to choosing a better candidate based on the size-of-array initializer list. Consider the following test:

    void f(int const(&)[2]);
    void f(int const(&)[3]) = delete;
    
    void g()
    {
      f({1, 2});
    }
    

    GCC 9 rejects this test because it can't decide which candidate is better. Yet it seems obvious that the first candidate is best (never mind the = delete part; deleted functions participate in overload resolution). GCC 10 chooses this option, which lets the code compile.

    Note: You can find the overall defect resolution status on the C++ Defect Report Support in GCC page.

    Conclusion

    In GCC 11, we plan to finish up the remaining C++20 features. For progress so far, see the C++2a Language Features table on the C++ Standards Support in GCC page. GCC 11 will also switch the default dialect to C++17 (it has already happened). Please do not hesitate to file bugs in the meantime, and help us make GCC even better!

    Acknowledgments

    I'd like to thank my coworkers at Red Hat who made the GNU C++ compiler so much better, notably Jason Merrill, Jakub Jelinek, Patrick Palka, and Jonathan Wakely.

    Last updated: February 5, 2024

    Recent Posts

    • Container starting and termination order in a pod

    • More Essential AI tutorials for Node.js Developers

    • How to run a fraud detection AI model on RHEL CVMs

    • How we use software provenance at Red Hat

    • Alternatives to creating bootc images from scratch

    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Products

    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform

    Build

    • Developer Sandbox
    • Developer Tools
    • Interactive Tutorials
    • API Catalog

    Quicklinks

    • Learning Resources
    • E-books
    • Cheat Sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site Status Dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Report a website issue