With C++20, we got new and improved attributes such as [[nodiscard(“reason”)]], [[likely]], [[unlikely]], and [[no_unique_address]]. In particular, [[nodiscard(“reason”)]] allows it to express the intention of your interface way clearer.
Attributes allow it to express declaratively the intention of your code.
During the writing of this article, I become a big fan of [[nodiscard(“reason”)]]. Consequently, I want to start with my favorite.
We have [[nodiscard]] already since C++17. C++20 added the possibility to add a message to the attribute. Unfortunately, I ignored [[nodiscard]] in the last few years. Let me present it now. Imagine, I have the following program.
Thanks to perfect forwarding and parameter packs, the factory function create can call any constructor and return a heap-allocated object.
The program has many issues. First, line (1) has a memory leak because the heap created int is never destroyed. Second, the error code of the function errorPronceFunction (2) is not checked. Last, the constructor call MyType(5, true) creates a temporary, which is created and immediately destroyed. This is at least a waste of resources. Now, [[nodiscard]] comes into play.
[[nodiscard]] can be used in a function, enumeration, or class declaration. If you discard the return value from a function declared as nodiscard, the compiler should issue a warning. The same holds for a function returning by copy an enumeration or a class declared as [[nodiscard]]. A cast-to-void should not emit a warning.
Let me see what this means. In the following example, I use the C++17 syntax of the attribute [[nodiscard]].
The factory function create and the enum ErrorCode is declared as [[nodiscard]]. Consequently, calls (1) and (2) create a warning.
Way better, but the program still has a few issues. [[nodiscard]] cannot be used for functions such as a constructor returning nothing. Therefore, the temporary MyType(5, true) is still created without warning. Second, the error messages are too general. As a user of the functions, I want a reason why discarding the result is an issue.
Both issues can be solved with C++20. Constructors can be declared as [[nodiscard]], and the warning could have additional information.
Now, the user of the functions gets a specific message. Here is the output of the Microsoft compiler.
By the way, many existing functions in C++ could benefit from the [[nodiscard]] attribute. For example, when you don’t use the return value of std::asnyc, an asynchronously meant std::async call becomes implicitly synchronous. What should run in a separate thread behaves as a blocking function call. Read more about the counterintuitive behavior of std::async in my blog “The Special Futures“.
While studying the [[nodiscard]] syntax on cppreference.com, I noticed that the overload of std::async changed with C++20. Here is one:
std::future as return-type of the promise std::async is declared as [[nodiscard]].
The following two attributes [[likely]] and [[unlikely]], are about optimization.
[[likely]] and [[unlikely]]
The proposal P0479R5 for likely and unlikely attributes is the shortest proposal I know of. To give you an idea, this is an interesting note to the proposal. “The use of the likely attribute is intended to allow implementations to optimize for the case where paths of execution including it are arbitrarily more likely than any alternative path of execution that does not include such an attribute on a statement or label. The use of the unlikely attribute is intended to allow implementations to optimize for the case where paths of execution including it are arbitrarily more unlikely than any alternative path of execution that does not include such an attribute on a statement or label. A path of execution includes a label if and only if it contains a jump to that label. Excessive usage of either of these attributes is liable to result in performance degradation.”
To make it short, both attributes allow it to give the optimizer a hint about which path of execution is more or less likely.
The story with optimization goes on with the new attribute [[no_unique_address]]. This time the optimization addresses space.
[[no_unique_address]] expresses that this data member of a class need not have an address distinct from all other non-static data members of its class. Consequently, if the member has an empty type, the compiler can optimize it to occupy no memory.
The following program exemplifies the usage of the new attribute.
The class NoUniqueAddress has another size as an int (2) but not the class UniqueAddress (3). The members d and e of NoUniqueAddress (4) have different addresses but not the members of the class UniqueAddress (5).
The volatile qualifier is one of the darkest corners in C++. Consequently, most of volatile has been deprecated in C++20.
Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Jozo Leko, John Breland, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Daniel Hufschläger, Alessandro Pezzato, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Leo Goodstadt, John Wiederhirn, Yacob Cohen-Arazi, Florian Tischler, Robin Furness, Michael Young, Holger Detering, Bernd Mühlhaus, Matthieu Bolt, Stephen Kelley, Kyle Dean, Tusar Palauri, Dmitry Farberov, Juan Dent, George Liao, Daniel Ceperley, Jon T Hess, Stephen Totten, Wolfgang Fütterer, Matthias Grün, Phillip Diekmann, Ben Atakora, Ann Shatoff, Rob North, Bhavith C Achar, and Marco Parri Empoli.
Thanks, in particular, to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, John Nebel, Mipko, Alicja Kaminska, Slavko Radman, and David Poole.
|My special thanks to Embarcadero|
|My special thanks to PVS-Studio|
|My special thanks to Tipi.build|
|My special thanks to Take Up Code|
I’m happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.
- Embedded Programmierung mit modernem C++ 12.12.2023 – 14.12.2023 (Präsenzschulung, Termingarantie)
Standard Seminars (English/German)
Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.
- C++ – The Core Language
- C++ – The Standard Library
- C++ – Compact
- C++11 and C++14
- Concurrency with Modern C++
- Design Pattern and Architectural Pattern with C++
- Embedded Programming with Modern C++
- Generic Programming (Templates) with C++
- Clean Code with Modern C++
- Phone: +49 7472 917441
- Mobil:: +49 176 5506 5086
- Mail: schulung@ModernesCpp.de
- German Seminar Page: www.ModernesCpp.de
- Mentoring Page: www.ModernesCpp.org
Modernes C++ Mentoring,