ErbslandDEV C++ Code Style Summary
This guide defines the basic C++ style conventions used across ErbslandDEV codebases. It is focused on clarity, maintainability, and practical modern C++ usage.
Naming Conventions
Classes: PascalCase (e.g.,
Controller
,TestClassBase
)Methods and Functions: camelCase (e.g.,
addTestClass
,parseCommandLine
)Member Variables:
_underscorePrefix
(e.g.,_console
,_testClasses
)Global Constants:
cExample
if not in dedicated namespace.Namespaces: all lowercase with nested structure (e.g.,
erbsland::unittest
)Preprocessor Macros: all uppercase
EXAMPLE
File Organization
Header Guards: Use
#pragma once
Include Order (separate blocks with empty lines): 1. Corresponding header (if in
.cpp
) — followed by two empty lines 2. Local includes:#include "Example.hpp"
3. Local subdirectory includes:#include "sub/sub/Example.hpp"
4. Local relative includes:#include "../../Example.hpp"
5. Project libraries:#include <erbsland/core/String.hpp>
6. Standard library headers:#include <vector>
7. Two empty lines after the include blockFile Extensions: Use
.hpp
for headers,.cpp
for implementationsFile Scope: Aim for one class per file, with matching name
Maximum File Length: Try to keep files under 500 lines
Formatting
Indentation: 4 spaces, no tabs
Line Length: Target a maximum of 120 characters per line
Braces: Opening brace stays on the same line
Spacing and Separation: - Use empty lines to separate logical blocks - One empty line between function definitions if they span >3 lines or have documentation - Two empty lines around
struct
,class
, orenum
definitions - Two empty lines around function implementations in.cpp
files
Constants & Literals
Prefer
constexpr
orconst
where applicableNever use macros for constants
Move mechanic requires mutable instances!
Modern C++ Usage
Use C++20 syntax
Always use trailing return types for all non-void functions:
auto create() -> std::string;
Use
auto
when the type is obvious or improves readabilityUse structured binding
const auto &[a, b] =
Use
[[nodiscard]]
andnoexcept
where applicableUse
override
for overwritten/implemented functionsUse
final
for final classesUse designated initialization if it improves the readability of the code
Use
std::unique_ptr
/std::shared_ptr
instead of raw pointersPrefer range-based
for
loopsUse
std::format
andstd::chrono
for formatted output and timingPrefer
std::ranges
andstd::views
for expressive algorithms
Quality and Safety First
Avoid manual memory management and raw pointers
Trust the compiler to optimize; prioritize clarity over micro-optimization
Perform bounds and range checks
Write unit tests for all modules and key functions
Ensure good test coverage and fail clearly when things go wrong
A crash is better than silent failure or undefined behavior
Comments
Public API Docs: Use
///
and Doxygen@
-syntaxInline Comments: Use
//
for short clarifying notesBlock Comments: Avoid
/* ... */
unless necessarySpecial Doxygen Tags: -
@tested
: Indicates this is covered by a unit test (name or path to the tests) -@notest
: Explains why a unit test is not applicable -@needtest
: Flags untested functionality -@wip
: This part is work in progress—talk to the author before modifying