C++ style guide lineup

11th of February, 2016
C/C++

Recently, I was recently asked to help out in a C++ project. One of the first things, I realized – apart from the horrible lack of documentation – was that there was no coding style.

At first inconsistant indentation bugged me. But, after a while I realized that the mixed casing styles (e.g. doThis() and do_that()) slowed me down while coding. So, I took a little break from programming and prepared a decision ground for my fellow colleagues. While googling for standards, I could not find a good side-by-side comparison.

The goal

I wanted to have one sheet of paper for each coding style, so each team member can get a quick impression of the formatting. The sheet should help to identify the aspects they like and which the do not. Ideally, after a few minutes of discussion we could decide on one and I can run an automated tool to reformat the code1.

The standards

I decided to include the following five standards: LLVM, Google, Chromium, Mozilla and WebKit. Why those five? Because clang-format supports them out of the box.

Since, we were only looking at formatting aspects for now, we investigated casing, indentation and line breaks for the following constructs:

Now without further ado, here the examples:

LLVM

This is a very abbreviated version of this file.

enum ShootingHand { SH_Left, SH_Right }; // use upper-case initials as prefix

class Cowboy {
  int getAge() { return Age; };
  // lower, camel case for function names
  // uppercase, camel case for variable/parameters 
  void shoot(std::string Who); // lower, camel case for function names, uppercase, camel case for variable/parameters 
  // upercase, camel case for members
  int GunCount;
}

Cowboy::~Cowboy() { std::cout << "RIP" << std::endl; }

void Cowboy::shoot(std::string Who) {
  Age++;
  int SomeNumber = 5 + 7 * 3;
  makeBang(SomeNumber);
  if (SomeNumber > 10) {
    return;
  }
  switch (Age) {
  case 45:
    Age--;
    break;
  default:
    Age++;
  }
}

void Cowboy::makeBang(const int &HowMany) {
  for (int i = 0; i < HowMany; ++i)
    std::cout << "Bang!" << std::endl;
}

Google

This is a very abbreviated version of this file.

enum ShootingHand { kLeft, kRight };

class Cowboy {
 public:
  void Shoot(std::string who); // upercase, camel case for functions
  int get_age() { return age_; }  // minor functions have lower case

 protected: // single space indentation on the left
  void MakeBang(const int &how_many);

  int gun_count_; // members with underscore suffix
};

Cowboy::Cowboy() : age_(45), gun_count_(2) {
  std::cout << "I am alive!" << std::endl;
}

void Cowboy::Shoot(std::string who) {
  age_++;
  int some_number = 5 + 7 * 3;
  MakeBang(some_number);
  if (some_number > 10) {
    return;
  }
  switch (age_) {
    case 45:
      age_--;
      break;
    default:
      age_++;
  }
}

void Cowboy::MakeBang(const int &how_many) {
  for (int i = 0; i < how_many; ++i) std::cout << "Bang!" << std::endl;
}

void someVeryLongMethod(int param1, int param2, int param3, int param4,
                        int param5, int param6, int param7, int param8,
                        int param9, int param10) {
  std::cout << "So long..." << std::endl;
}

Chromium

This is a very abbreviated version of this file

// like google, but with a few exceptions
enum ShootingHand { LEFT, RIGHT }; // 

void Cowboy::MakeBang(const int& how_many) {
  for (int i = 0; i < how_many; ++i)
    std::cout << "Bang!" << std::endl;
}

void someVeryLongMethod(int param1,
                        int param2,
                        int param3,
                        int param4,
                        int param5,
                        int param6,
                        int param7,
                        int param8,
                        int param9,
                        int param10) {
  std::cout << "So long..." << std::endl;
}

Mozilla

This is a very abbreviated version of this file.

enum ShootingHand
{
  kLeft,
  kRight
};

class Cowboy
{
public:
  void Shoot(std::string aWho);

protected:
  int mGunCount; // members are prefixed with m
};

Cowboy::Cowboy() // very much space everywhere
  : mAge(45)
  , mGunCount(2)
{
  std::cout << "I am alive!" << std::endl;
}

void
Cowboy::Shoot(std::string aWho)
{
  mAge++;
  int someNumber = 5 + 7 * 3;
  MakeBang(someNumber);
  if (someNumber > 10) {
    return;
  }
  switch (mAge) {
    case 45:
      mAge--;
      break;
    default:
      mAge++;
  }
}

WebKit

This is a very abbreviated version of this file.

enum ShootingHand {
    kLeft,
    kRight
};

class Cowboy {
public:
    void shoot(std::string who);

protected:
    int m_gunCount; // members prefixed with m_
};

Cowboy::Cowboy()
    : m_age(45)
    , m_gunCount(2)
{
    std::cout << "I am alive!" << std::endl;
}

void Cowboy::shoot(std::string who)
{
    m_age++;
    int someNumber = 5 + 7 * 3;
    makeBang(someNumber);
    if (someNumber > 10) {
        return;
    }
    switch (m_age) {
    case 45:
        m_age--;
        break;
    default:
        m_age++;
    }
}

How it worked out

I printed out the sheets, we looked at them for five minutes in silence. Then we discussed them for another ten minutes and picked one. We decided to deviate in three minor points to make all members happy (you’ve got to compromise, right?).
More specifically, we went for the LLVM style with a column limit of 150 characters, indented case labels and all capital enum labels. I was surprised that it went so smoothly.

I have uploaded all examples into this repository.

  1. Unfortunately, clang-format is not as powerful as other tools, so we had to fix the casing manually. This wasn’t too bad, because a major refactor was in order anyway.