66
votes

What are your favorite C++ coding style idioms? I'm asking about style or coding typography such as where you put curly braces, are there spaces after keywords, the size of indents, etc. This is opposed to best-practices or requirements such as always deleting arrays with delete[].

Here is an example of one of my favorites: In C++ Class initializers, we put the separators at the front of the line, rather than the back. This makes it easier to keep this up to date. It also means that source code control diffs between versions are cleaner.

TextFileProcessor::
TextFileProcessor( class ConstStringFinder& theConstStringFinder ) 

    : TextFileProcessor_Base( theConstStringFinder )

    , m_ThreadHandle  ( NULL )
    , m_startNLSearch (    0 )
    , m_endNLSearch   (    0 )
    , m_LineEndGetIdx (    0 )
    , m_LineEndPutIdx (    0 )
    , m_LineEnds      ( new const void*[ sc_LineEndSize ] )
{
    ;
}
24
It would be better to post your example as an answer ;-)Leon Timmermans
You are talking about coding style here, not idioms.Nemanja Trifunovic

24 Answers

61
votes

When creating enumerations, put them in a namespace so that you can access them with a meaningful name:

namespace EntityType {
    enum Enum {
        Ground = 0,
        Human,
        Aerial,
        Total
    };
}

void foo(EntityType::Enum entityType)
{
    if (entityType == EntityType::Ground) {
        /*code*/
    }
}

EDIT: However, this technique has become obsolete in C++11. Scoped enumeration (declared with enum class or enum struct) should be used instead: it is more type-safe, concise, and flexible. With old-style enumerations the values are placed in the outer scope. With new-style enumeration they are placed within the scope of the enum class name.
Previous example rewritten using scoped enumeration (also known as strongly typed enumeration):

enum class EntityType {
    Ground = 0,
    Human,
    Aerial,
    Total
};

void foo(EntityType entityType)
{
    if (entityType == EntityType::Ground) {
        /*code*/
    }
}

There are other significant benefits from using scoped enumerations: absence of implicit cast, possible forward declaration, and ability to use custom underlying type (not the default int).

71
votes

RAII: Resource Acquisition Is Initialization

RAII may be the most important idiom. It is the idea that resources should be mapped to objects, so that their lifetimes are managed automatically according to the scope in which those objects are declared.

For example, if a file handle was declared on the stack, it should be implicitly closed once we return from the function (or loop, or whichever scope it was declared inside). If a dynamic memory allocation was allocated as a member of a class, it should be implicitly freed when that class instance is destroyed. And so on. Every kind of resource—memory allocations, file handles, database connections, sockets, and any other kind of resource that has to be acquired and released—should be wrapped inside such a RAII class, whose lifetime is determined by the scope in which it was declared.

One major advantage of this is that C++ guarantees that destructors are called when an object goes out of scope, regardless of how control is leaving that scope. Even if an exception is thrown, all local objects will go out of scope, and so their associated resources will get cleaned up.

void foo() {
  std::fstream file("bar.txt"); // open a file "bar.txt"
  if (rand() % 2) {
    // if this exception is thrown, we leave the function, and so
    // file's destructor is called, which closes the file handle.
    throw std::exception();
  }
  // if the exception is not called, we leave the function normally, and so
  // again, file's destructor is called, which closes the file handle.
}

Regardless of how we leave the function, and of what happens after the file is opened, we don't need to explicitly close the file, or handle exceptions (e.g. try-finally) within that function. Instead, the file gets cleaned up because it is tied to a local object that gets destroyed when it goes out of scope.

RAII is also less-commonly known as SBRM (Scope-Bound Resource Management).

See also:

  • ScopeGuard allows code to "automatically invoke an 'undo' operation .. in the event that an exception is thrown."
40
votes

Copy-swap

The copy-swap idiom provides exception-safe copying. It requires that a correct copy ctor and swap are implemented.

struct String {
  String(String const& other);

  String& operator=(String copy) { // passed by value
    copy.swap(*this); // nothrow swap
    return *this; // old resources now in copy, released in its dtor
  }

  void swap(String& other) throw() {
    using std::swap; // enable ADL, defaulting to std::swap
    swap(data_members, other.data_members);
  }

private:
  Various data_members;
};
void swap(String& a, String& b) { // provide non-member for ADL
  a.swap(b);
}

You can also implement the swap method with ADL (Argument Dependent Lookup) directly.

This idiom is important because it handles self-assignment[1], makes the strong exception guarantee[2], and is often very easy to write.


[1] Even though self-assignment isn't handled as efficiently as possible, it's supposed to be rare, so if it never happens, this is actually faster.

[2] If any exception is thrown, the state of the object (*this) is not modified.

34
votes

CRTP: Curiously Recurring Template Pattern

CRTP happens when you pass a class as a template parameter to its base class:

template<class Derived>
struct BaseCRTP {};

struct Example : BaseCRTP<Example> {};

Within the base class, it can get ahold of the derived instance, complete with the derived type, simply by casting (either static_cast or dynamic_cast work):

template<class Derived>
struct BaseCRTP {
  void call_foo() {
    Derived& self = *static_cast<Derived*>(this);
    self.foo();
  }
};

struct Example : BaseCRTP<Example> {
  void foo() { cout << "foo()\n"; }
};

In effect, call_foo has been injected into the derived class with full access to the derived class's members.

Feel free to edit and add specific examples of use, possibly to other SO posts.

28
votes

pImpl: Pointer-to-Implementation

The pImpl idiom is a very useful way to decouple the interface of a class from its implementation.

Normally, a class definition must contain member variables as well as methods, which may expose too much information. For example, a member variable may be of a type defined in a header that we don't wish to include everywhere.

The windows.h header is a prime example here. We may wish to wrap a HANDLE or another Win32 type inside a class, but we can't put a HANDLE in the class definition without having to include windows.h everywhere the class is used.

The solution then is to create a Private IMPLementation or Pointer-to-IMPLementation of the class, and let the public implementation store only a pointer to the private one, and forward all member methods.

For example:

class private_foo; // a forward declaration a pointer may be used

// foo.h
class foo {
public:
  foo();
  ~foo();
  void bar();
private:
  private_foo* pImpl;
};

// foo.cpp
#include whichever header defines the types T and U

// define the private implementation class
class private_foo {
public:
  void bar() { /*...*/ }

private:
  T member1;
  U member2;
};

// fill in the public interface function definitions:
foo::foo() : pImpl(new private_foo()) {}
foo::~foo() { delete pImpl; }
void foo::bar() { pImpl->bar(); }

The implementation of foo is now decoupled from its public interface, so that

  • it can use members and types from other headers without requiring these dependencies to be present when the class is used, and
  • the implementation can be modified without forcing a recompile of the code that uses the class.

Users of the class simply include the header, which contains nothing specific about the implementation of the class. All implementation details are contained inside foo.cpp.

23
votes

I like lining up code/initializations in 'columns'... Proves very useful when editing with a 'column' mode capable editor and also seems to be a lot easier for me to read...

int myVar        = 1;    // comment 1
int myLongerVar  = 200;  // comment 2

MyStruct arrayOfMyStruct[] = 
{   
    // Name,                 timeout,   valid
    {"A string",             1000,      true    },   // Comment 1
    {"Another string",       2000,      false   },   // Comment 2 
    {"Yet another string",   11111000,  false   },   // Comment 3
    {NULL,                   5,         true    },   // Comment 4
};

In contrast, the same code not indented and formatted as above would appear... (A little harder to read to my eyes)

int myVar = 1; // comment 1
int myLongerVar = 200; // comment 2

MyStruct arrayOfMyStruct[] = 
{   
    // Name, timeout, valid
    {"A string", 1000, true},// Comment 1
    {"Another string", 2000, false }, // Comment 2 
    {"Yet another string", 11111000,false}, // Comment 3
    {NULL, 5, true }, // Comment 4
};
16
votes

Public Top - Private Down

A seemingly small optimization, but ever since I switched to this convention, I have a way more fun time to grasp my classes, especially after I haven't looked at them for 42 years.

Having a consistent member visibility, going from points of frequent interest down to the boring stuff, is extremely helpful, especially when the code ought to be self-documenting.

(sidenote for qt-users: slots come before signals because they should be callable like non-slot member functions, and apart from their slottyness be indistinguishable from non-slots)

  • Public, protected, private
  • then Factory, ctor, dtor, copying, swapping
  • then the class' Interface At the very last, in a seperate private: section, comes the data (ideally only an impl-pointer).

This rule also helps a ton if you have problems keeping your class declaration uncluttered.

class Widget : public Purple {
public:
    // Factory methods.
    Widget FromRadians (float);
    Widget FromDegrees (float);

    // Ctors, rule of three, swap
    Widget();
    Widget (Widget const&);
    Widget &operator = (Widget const &);
    void swap (Widget &) throw();

    // Member methods.
    float area() const;

    // in case of qt {{ 
public slots:
    void invalidateBlackHole();

signals:
    void areaChanged (float);
    // }}

protected:    
    // same as public, but for protected members


private:    
    // same as public, but for private members

private:
    // data
    float widgetness_;
    bool  isMale_;
};
12
votes

In if statements, when there are difficult conditions, you can clearly show which level each condition is using indentation.

if (  (  (var1A == var2A)
      || (var1B == var2B))
   && (  (var1C == var2C)
      || (var1D == var2D)))
{
   // do something
}
8
votes

Compile-time polymorphism

(Also known as syntactic polymorphism and static polymorphism, contrast with runtime polymorphism.)

With template functions, one can write code that relies on type constructors and call signatures of families of parametrized types, without having to introduce a common base class.

In the book Elements of Programming, the authors refer to this treatment of types as abstract genera. With concepts one can specify the requirements on such type parameters, though C++ doesn't mandate such specifications.

Two simple examples:

#include <stdexcept>

template <typename T>
T twice(T n) {
  return 2 * n;
}

InIt find(InIt f, InIt l,
          typename std::iterator_traits<InIt>::reference v)
{
  while (f != l && *f != v)
    ++f;
  return f;
}   

int main(int argc, char* argv[]) {
  if (6 != twice(3))
    throw std::logic_error("3 x 2 = 6");

  int const nums[] = { 1, 2, 3 };
  if (nums + 4 != find(nums, nums + 4, 42))
    throw std::logic_error("42 should not have been found.");

  return 0;
}

One can call twice with any regular type that has a binary * operator defined. Similarly, one can call find() with any types that are comparable and that model Input Iterator. One set of code operates similarly on different types, with no shared base classes in sight.

Of course, what's really going on here is that it's the same source code being expanded into various type-specific functions at template instantiation time, each with separate generated machine code. Accommodating the same set of types without templates would have required either 1) separate hand-written functions with specific signatures, or 2) runtime polymorphism through virtual functions.

7
votes

No favorites but I will fix code that has:

  1. tabs - causes misalignment in many IDEs and code review tools, because they don't always agree on tab at mod 8 spaces.
  2. lines longer than 80 columns - let's face it, shorter lines are more readable. My brain can parse most coding conventions, as long as the lines are short.
  3. lines with trailing whitespaces - git will complain about it as whitespace errors, which show up as red blobs in diffs, which is annoying.

Here is a one-liner to find the offending files:

git grep -I -E '<tab>|.{81,}|  *$' | cut -f1 -d: | sort -u

where <tab> is the tab character (POSIX regexp doesn't do \t)

7
votes

re: ididak

I fix code that breaks long statements into too many short lines.

Let's face it: it's not the 90's any more. If your company can't afford widescreen LCDs for its coders, you need to get a better job :)

6
votes

if/while/for parenthesized expression(s) WITH a space separator

if (expression)  // preferred - if keyword sticks out more

vs.

if(expression)  // looks too much like a void function call

I guess this implies that I like my function calls to NOT have a space separator

foo(parm1, parm2);
5
votes

After working with someone who was partly blind - and at his request - I switched to using many more spaces. I didn't like it at the time, but now I prefer it. Off the top of my head, the only place where there isn't whitespace between identifiers and keywords and whatnot is after a function name and before the following parentheses.

void foo( int a, int b )
{
  int c = a + ( a * ( a * b ) );
  if ( c > 12 )
    c += 9;
  return foo( 2, c );
}
5
votes

Template and Hook

This is a way to handle as much as possible in a framework and give a door or hook for customization by users of a framework. Also known as Hotspot and Template Method.

class Class {
  void PrintInvoice();     // Called Template (boilerplate) which uses CalcRate()
  virtual void CalcRate() = 0;  // Called Hook
}

class SubClass : public Class {
  virtual void CalcRate();      // Customized method
}

Described by Wolfgang Pree in his book Design Patterns for Object-Oriented Software Development.

4
votes

I don't know if it qualifies as an idiom, exactly, but quite a bit of heavy-duty template programming depends (often heavily) on SFINAE (substitution failure is not an error). A couple of the answers to a previous question have examples.

4
votes

I really like putting a small statement on the same line as an if

int myFunc(int x) {
   if(x >20) return -1;
   //do other stuff ....
}
4
votes

Not sure if this counts as an idiom, but I tend to use doxygen-style inline comments even when the project isn't -yet- using doxygen...

bool MyObjects::isUpToSomething() ///< Is my object up to something 

(aside. my comments are not usually quite that lame.)

2
votes

It's useful to put function names on a new line, so you can grep like

grep -R '^fun_name' .

for them. I've seen that style used for a loads of GNU projects and like it:

static void
fun_name (int a, int b) {
    /* ... */
}
2
votes

Document the return values on the function line, so they are very easy to find.

int function(void) /* return 1 on success, 0 on failure */ 
{
    return 1;
};
1
votes

Write each method or function argument on a separate line such that it can be easily commented.

int ReturnMaxValue(
    int* inputList,   /* the list of integer values from which to get the maximum */
    long size,        /* count of the number of integer values in inputList */
    char* extraArgs   /* additional arguments that a caller can provide.    */
)
1
votes

I'd suggest PIMPL or as James Coplien originally called it "Handle Body".

This idiom allows you to completely decouple interface from implementation. When working on the rewrite and re-release of a major CORBA middleware component, this idiom was used to completely decouple the API from the implementation.

This practically eliminated any possibility reverse engineering.

An excellent resource for C++ idioms is James Coplien's excellent book "Advanced C++ Programming Styles and Idioms". Highly recommended!

Edit: As pointed out below by Neil, this book is quite out of date with many of his recommendations actually being incorporated into the C++ standard itself. However, I still find it to be a source of useful info, esp. in the form of his PLoP paper on C++ idioms where many idioms were recast into patterm form.

0
votes

I always nitpick and edit the following:

  • Superfluous newlines
  • No newline at EOF
0
votes

I usually stick to KNF described in *BSD STYLE(9)

-1
votes

I tend to put an else on all of my ifs.

if (condition)
{
    complicated code goes here
}
else
{
    /* This is a comment as to why the else path isn't significant */ 
}

Even though it annoys my coworkers. You can tell at a glance, that I considered the else case during coding.