Skip to main content
AI
  • Get started with AI

    • Red Hat AI

      Accelerate the development and deployment of enterprise AI solutions.

    • AI learning hub

      Explore learning materials and tools, organized by task.

    • AI interactive demos

      Click through scenarios with Red Hat AI, including training LLMs and more.

    • AI/ML learning paths

      Expand your Red Hat OpenShift AI knowledge using these learning resources.

    • AI quickstarts

      Focused AI use cases designed for fast deployment on Red Hat AI platforms.

    • No-cost AI training

      Foundational Red Hat AI training.

  • Featured resources

    • Red Hat OpenShift AI
    • Open source AI for developers
    • AI product application development
    • Open source-powered AI/ML for hybrid cloud
    • AI and Node.js cheat sheet

Red Hat AI Factory with NVIDIA

Red Hat AI Factory with NVIDIA is a co-engineered, enterprise-grade AI solution for building, deploying, and managing AI at scale across hybrid cloud environments.

Learn
  • Self-guided

    • Documentation

      Find answers, get step-by-step guidance, and learn how to use Red Hat products.

    • Learning paths

      Explore curated walkthroughs for common development tasks.

    • Guided learning

      Receive custom learning paths powered by our AI assistant.

    • See all learning
  • Hands-on

    • Developer Sandbox

      Spin up Red Hat's products and technologies without setup or configuration.

    • Interactive labs

      Learn by doing in these hands-on, browser-based experiences.

    • Interactive demos

      Click through product features in these guided tours.

  • Browse by topic

    • AI/ML
    • Automation
    • Java
    • Kubernetes
    • Linux
    • See all topics
  • Training & certifications

    • Courses and exams
    • Certifications
    • Skills assessments
    • Red Hat Academy
    • Learning subscription
    • Explore training
Build
  • Get started

    • Red Hat build of Podman Desktop

      A downloadable, local development hub to experiment with our products and builds.

    • Developer Sandbox

      Spin up Red Hat's products and technologies without setup or configuration.

  • Download products

    • Red Hat Enterprise Linux
    • Red Hat AI
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products
  • Featured

    • Red Hat build of OpenJDK
    • Red Hat JBoss Enterprise Application Platform
    • Red Hat OpenShift Dev Spaces
    • Red Hat Developer Toolset
  • References

    • E-books
    • Documentation
    • Cheat sheets
    • Architecture center
Community
  • Get involved

    • Events
    • Live AI events
    • Red Hat Summit
    • Red Hat Accelerators
    • Community discussions
  • Follow along

    • Articles & blogs
    • Developer newsletter
    • Videos
    • Github
  • Get help

    • Customer service
    • Customer support
    • Regional contacts
    • Find a partner

Join the Red Hat Developer program

Download Red Hat products and project builds, access support documentation, learning content, and more.

ConsoleDocsSupport Search
New For you

Recommended

We'll recommend resources you may like as you browse. Try these suggestions for now.

  • Product downloads
  • Cheat sheets
  • Red Hat Developer learning portal
  • Developer blog
  • E-books
  • Developer Sandbox
Log in

Get more with a Red Hat Developer account

  • Product downloads
  • Console access
  • Event registration
  • Training & trials
Explore more account benefitsLog in or register

A subscription may be required for some services.

Contact us

New C++ features in GCC 10

<p>&nbsp;</p> <quillbot-extension-portal></quillbot-extension-portal>

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

    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

    • A day in the life of an NVIDIA H100 on Red Hat OpenShift 5

    • Migrate BuildConfigs to builds for Red Hat OpenShift with one plug-in install

    • Run Red Hat Enterprise Linux CoreOS on NVIDIA BlueField DPUs

    • Agent harness engineering: Separating model capabilities from enforcement

    • What's new for developers in Red Hat Enterprise Linux 10.3 and 9.9

    Red Hat Developers logo

    Platforms

    • Red Hat AI
    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products

    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
    © 2026 Red Hat

    Red Hat legal and privacy links

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