mistake 968334 1280

C++ Core Guidelines: Naming and Layout Rules

The C++ core guidelines have about twenty naming and layout rules. A few of them are obvious; a few of them may be controversial. Let’s see what I mean.

 

 mistake 968334 1280

Naming and Layout Rules

First of all, consistency is more important than these naming and layout rules. With this in mind, here is an overview of the rules.

  • NL.1: Don’t say in comments what can be clearly stated in the code
  • NL.2: State intent in comments
  • NL.3: Keep comments crisp
  • NL.4: Maintain a consistent indentation style
  • NL.5: Don’t encode type information in names
  • NL.7: Make the length of a name roughly proportional to the length of its scope
  • NL.8: Use a consistent naming style
  • NL.9: Use ALL_CAPS for macro names only
  • NL.10: Avoid CamelCase
  • NL.11: Make literals readable
  • NL.15: Use spaces sparingly
  • NL.16: Use a conventional class member declaration order
  • NL.17: Use K&R-derived layout
  • NL.18: Use C++-style declarator layout
  • NL.19: Avoid names that are easily misread
  • NL.20: Don’t place two statements on the same line
  • NL.21: Declare one name (only) per declaration
  • NL.25: Don’t use void as an argument type
  • NL.26: Use conventional const notation

I will not write about the naming and layout rules of the C++ core guidelines, which already have sufficient explanations. I only write about the rules, which need additional wording or are often discussed in my seminars.

NL.1: Don’t say in comments what can be clearly stated in the code

I’m not a friend of commenting on each piece of code. Commenting on each piece of code may be a code smell because you code it too sophisticated. I’m more with the Python rule: explicit is better than implicit. I only write a comment if I have to apply a trick that is not apparent. For example, young professionals tend to remove curly braces from their code, such as you would remove redundant round braces from an arithmetic expression. If you don’t believe me, visit my seminars. But curly braces are essential to scope RAII objects such as locks or smart pointers. Removing a curly brace from a lock may give you a slower program or a deadlock. In the end, many of my customers comment on using curly braces.

 

Rainer D 6 P2 500x500Modernes C++ Mentoring

Be part of my mentoring programs:

  • "Fundamentals for C++ Professionals" (open)
  • "Design Patterns and Architectural Patterns with C++" (open)
  • "C++20: Get the Details" (open)
  • "Concurrency with Modern C++" (starts March 2024)
  • Do you want to stay informed: Subscribe.

     

    std::mutex mut;
    {   // necessary to manage the lifetime of the lock
        std::lock_guard<std::mutex> lock(mut);
        ...
    }
    

     

    What is terrible about comments is that they become out of date. By definition, this is not possible for the source code. It’s always up to date.  As a freshman, my job was quite often to refactor legacy code. I often had no clue what it does, and I was pretty frustrated. To my rescue, I found a few comments. But the comments were completely outdated. It took me a while to recognize this; you can’t imagine how I felt. Comments have to be maintained as code but are often very sloppy maintained.

    NL.5: Don’t encode type information in names

    Really? I thought since the last millennium, we were done with Hungarian Notation. I mean these good old times in which our variables had no type. Hungarian Notation is redundant with the type-checking of the compiler, contradicts generic programming, and – this is my main argument – becomes outdated as comments become outdated. Can you guess for what the following variable names stand?

    bBusy;
    fBusy;
    pFoo;
    szLastName;
    fnFunction;
    pszOwner;
    rgfpBalances;
    lpszBar;
    g_nWhells;
    m_whells;
    _whells;
    

     

    If you don’t know, here is the solution: Hungarian Notation.

    NL.7: Make the length of a name roughly proportional to the length of its scope

    This rule sounds strange, but we are already used to it. Giving a variable the name i or j or the name T will immediately make the code’s intention clear: i and j are indices, and T is a template type parameter.

    template<typename T>    
    void print(ostream& os, const vector<T>& v)
    {
        for (int i = 0; i < v.size(); ++i)
            os << v[i] << '\n';
    }
    

     

    There is a meta-rule behind this rule. A name should be self-explanatory. In a short context, you get what the variable means with a glance. This self-evidence will not automatically hold for more extended contexts; therefore, you should use longer names.

    NL.16: Use a conventional class member declaration order

    Okay, this is an easy but quite helpful rule.

    • When you declare a class, use the following order: constructors, assignments, destructor before functions, and data.
    • The same goes for public, protected, and private: Use the public before protected before private order.
    • Don’t use the access specifiers in a class more than once:
    class X {   // bad
    public:
        void f();
    public:
        int g();
        // ...
    };
    

    NL.19: Avoid names that are easily misread

    Can you read this example without any hesitation?

    if (readable(i1 + l1 + ol + o1 + o0 + ol + o1 + I0 + l0)) surprise();

     

    Honestly, I often have issues when I type in a password having the number 0 or the significant capital O. Two years ago; it took me quite a time to log into a server. The automatically generated password had a character O.

    NL.20: Don’t place two statements on the same line

    Let me give you two examples. Did you spot the two issues?

    char* p, p2;
    char a = 'a';
    p = &a;
    p2 = a;                              // (1)
    
    int a = 7, b = 9, c, d = 10, e = 3;  // (2)
    

     

    p2 is a char  (1), and c is not initialized (2).

    With C++17, we got an exception to this rule: structured binding. Structured binding allows me to declare more than one name in one declaration (line 1).

    Now, I can write the if statement with an initializer that is cleaner and more readable.

    std::map<int,std::string> myMap;
    
    if (auto [iter, succeeded] = myMap.insert(value); succedded){  // (1)
        useResult(iter);  
        // ...
    } 
    else{
        // ...
    } // iter and succeeded are automatically destroyed            
    

    What’s next?

    DONE! After over one hundred posts on the C++ core guidelines, I have two good pieces of news for you.

    First, I write a book about the C++ core guidelines, in which I try my best to make a readable and concise story out of this precious content. My idea is to base my story on C++17 and the C++ core guidelines rules, which are essential to writing modern C++. Of course, modern C++ means, in particular, writing type-safe, bounds safe, and lifetime safe C++ code. So, stay tuned; I will start in the next few days and give you an update if appropriate.

    Second, my blog will shift to the hot topic in C++: the upcoming C++20 standard. My posts start in a breadth-first search and will end in a depth-first search. C++20 is presumably as powerful as C++11. You can, therefore, assume that I have a lot to write. 

     

     

    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, 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, Marco Parri Empoli, moon, Philipp Lenk, Hobsbawm, and Charles-Jianye Chen.

    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
    My special thanks to SHAVEDYAKS

    Seminars

    I’m happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.

    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++
    • C++20

    Online Seminars (German)

    Contact Me

    Modernes C++ Mentoring,

     

     

    0 replies

    Leave a Reply

    Want to join the discussion?
    Feel free to contribute!

    Leave a Reply

    Your email address will not be published. Required fields are marked *