C++ code in the Carbon project should use a consistent and well documented style guide. Where possible, this should be enacted and enforced with tooling to avoid toil both for authors of C++ code in the Carbon project and for code reviewers.
However, we are not in the business of innovating significantly in the space of writing clean and maintainable C++ code, and so we work primarily to reuse existing best practices and guidelines.
The baseline style guidance is the Google C++ style guide.
We provide some local guidance beyond the baseline. This are typically motived either by specific value provided to the project, or to give simpler and more strict guidance for Carbon's narrow use of C++.
Carbon's C++ code tries to match the proposed Carbon naming convention as closely as is reasonable in C++ in order to better understand and familiarize ourselves with the practice of using this convention. It happens that this is fairly similar to the naming convention in the Google style guide and largely serves to simplify it.
UpperCamelCase, referencing Proper
Nouns.
constexpr variables, enumerators, etc.UpperCamelCase. The distinction between a virtual function and a
non-virtual function should be invisible, especially at the call site,
as that is an internal implementation detail. We want to be able to
freely change that without updating the name.snake_case, including function parameters, and
non-constant local and member variables.
_ suffix for member variable names.snake_case for files, directories, and build system rules.
Avoid -s in these as well..cpp for source files, which is the most common open source extension
and matches other places where "C++" is written without punctuation.These are minor issues where any of the options would be fine and we simply need
to pick a consistent option. Where possible,
clang-format should be used to enforce
these.
* adjacent to the type: TypeName* variable_name.const before the type when at the outer level: const int N = 42;.Only use line comments (with //, not /* ... */), on a line by
themselves, except for
argument name comments,
closing namespace comments,
and similar structural comments. In particular, don't append comments about
a line of code to the end of its line:
int bad = 42; // Don't comment here.
// Instead comment here.
int good = 42;
// Closing namespace comments are structural, and both okay and expected.
} // namespace MyNamespace
This dogfoods our planned commenting syntax for Carbon. It also provides a single, consistent placement rule. It also provides more resilience against automated refactorings. Those changes often make code longer, which forces ever more difficult formatting decisions, and can easily spread one line across multiple lines, leaving it impossible to know where to place the comment. Comments on their own line preceding such code, while still imprecise, are at least less confusing over the course of such refactorings.
Use the using-based type alias syntax instead of typedef.
Don't use using to support unqualified lookup on std types; for example,
using std::vector;. This also applies to other short namespaces,
particularly llvm and clang.
std:: gives clearer diagnostics and avoids any possible
ambiguity, particularly for ADL.std::swap that are
intentionally called using ADL. This pattern should be written as
{ using std::swap; swap(thing1, thing2); }.Follow the rules for initialization outlined in Abseil's tip #88. To summarize, omitting some details from the article:
=) when initializing directly with the intended
value (or with a braced initializer directly specifying that value).{} initialization without the = only if the above options don't
compile.{} initialization and auto.Always use braces for conditional, switch, and loop statements, even when
the body is a single statement.
switch statement, use braces after a case label when
necessary to create a scope for a variable.constexpr..clang-format contentsSee this repository's .clang-format file.