C++ Coding Standards

The following is not intended to generate a holy war, but merely a place for me to remind myself of the decisions I took along the way to get to a consistent style for any new code that I write.

IDE

Tabs set to 4, and set it to replace all tabs with spaces. Shift-Tab will backspace a tabs worth of spaces. Using spaces is so the code will look the same when cut and paste into other environments, like these blogs, email, and also online code links to godbolt.org

Compiler

-Wall and then turn off using pragma for any that are not needed.

Use C++ 11 for a simpler life and good compatibility. I am unlikely to use any of the new features. Well I do like if constexpr.

I found another nice C++17 feature. The default template declaration. It would mean you can have a class like cString<allocator=heap> and then call it without the template brackets.


enum allocator::source { heap, stack, new, malloc };
// No need for a custom source as it would just be added here.
// ...
cString<allocator::heap> test;
cString<> testUsingDefault;
cString<allocator::stack> faster;
// and replace it with
cString test;
cString<allocator::stack> faster;

Braces

Allman style with forced braces even for one line. Collapsing code into one neat little line is very tempting, but key reasons not to is for code readability and allowing for a place to step inside the debugger. Vertical space is not that critical if the code is clear and, simple and broken down to low Cyclomatic Complexity. I keep trying and can never get on with K&R style and its variants.

Identifiers

Take your pick from: camelCase, PascalCase, snake_case, SCREAMING_SNAKE_CASE.

My preference is camelCase as that is easier to type the snake_case, but the later feels more C++. Modern C++ have moved away from SCREAMING_SNAKE_CASE and I think that is a good move.

I tried snake_case for a while and the underscore is not that much of an issue because of the autocomplete. I still feel that camelCase is more readable and natural. It also takes up less space on a line.

camelCase it is then.

Hungarian or English?

I grew up with strong Hungarian notation and it makes sense in C where the typing is very weak. For modern C++ there is a view that this is not necessary any more as the compiler will warn of any conversions. That leaves member variable and static/global variables. While the m_ approach is nice, if you do that, then why not for everything.

My solution was arrived at by realising the member and static variables are to some degree special and that this can follow the direction indicated by the reserved cases for identifiers (__example, _ANOTHER). Thus, while using underscore is frowned upon, I like the notation to show the intent that these things are ‘part of inner code’. The same approach is to be used for static variables in the class or struct scope and also for local functions that clash with standard library versions.

class entity
{
    static constexpr size_t     _maxEntities = 1000;
    entity(char* name)
    {
        _name = name;
    };
    char    _name[8];
};

inline float _floor(const float& a);

For true global variable, use a single global struct call ‘g’. This allows for a central way to create a warning that these values must be written to very carefully.

struct globals
{
    int     count = 0;
    bool    isGameRunning = false;
}
struct globals g;
...
g.count++;    // Not thread safe.

camelCase can also be used for filenames. This is in contradiction to keeping all filenames lowercase to help with any accidental file use under windows due to case-insensitivity. But for consistency sake and a nice look it will be used here as well.

hashTable.h
imageScaler.h
vectorTests.cpp

Naming Conventions

size_t  n;          // For bytes in a buffer
int     i;          // For loops etc only
size_t  index;      // For array index - don't use 'i'
size_t  length;     // For char* only
size_t  size;       // For number of items in classes
size_t  capacity;   // For current max number of items
type    rhs;        // For operators overloads with lhs and rhs

Use nullptr over NULL to get the type information for the compiler.

Alignment

alignas
alignof
size_of

Align clasess and structures to 16 bytes unless they only contain char.

If using other backing memory then align to 16 bytes and make sure the class or struct is a multiple of 16 using packing

Comments from Various Sources

I’m a contract videogame programmer, so the answer is: I follow whatever the company guidelines call for. Typically, videogame code doesn’t use RTTI or exceptions, and follow CamelCase naming rules, m_ member variables, s_ static variables, and tab=4s. It’s remarkably consistent across the industry, for some reason. BoarsLair

Leave a Reply

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