forked from OSchip/llvm-project
[flang] C++ usage and style guide summary.
Original-commit: flang-compiler/f18@2cf1be7b05
This commit is contained in:
parent
55fe4d2af5
commit
ac12232e68
|
@ -0,0 +1,137 @@
|
|||
In brief:
|
||||
- Where LLVM's C++ style guide is clear, follow it.
|
||||
- Otherwise, where a clear precedent exists in the project, follow it.
|
||||
- Otherwise, where a good public C++ style guide is relevant and clear,
|
||||
follow it. (Google's is pretty good and comes with lots of justifications
|
||||
for its rules.)
|
||||
|
||||
Some particular points:
|
||||
|
||||
File names should use dashes, not underscores. C++ sources have the
|
||||
extension ".cc", not ".C" or ".cpp" or ".cxx". Don't create needless
|
||||
source directory hierarchies.
|
||||
|
||||
C++ names that correspond to STL names should look like those STL names
|
||||
(e.g., clear() and size() member functions).
|
||||
|
||||
Non-public data members should be named with leading miniscule (lower-case)
|
||||
letters, internal camelCase capitalization, and a trailing underscore,
|
||||
e.g. "DoubleEntryBookkeepingSystem myLedger_;". POD structures with
|
||||
only public data members shouldn't use trailing underscores, since they
|
||||
don't have class functions in which data members need to be distinguishable.
|
||||
Define only POD structures with "struct". Use "foo_" and "Bar(x)" in
|
||||
non-static member functions, not "this->foo_" and "this->Bar(x)".
|
||||
|
||||
Accessor member functions are named with the non-public data member's name,
|
||||
less the trailing underscore. Mutator member functions are named "set_..."
|
||||
and should return *this. Don't define accessors or mutators needlessly.
|
||||
|
||||
Other class functions should be named with leading capital letters,
|
||||
CamelCase, and no underscores, and, like all functions, should be based
|
||||
on imperative verbs, e.g. "HaltAndCatchFire()".
|
||||
|
||||
Header files should be idempotent:
|
||||
#ifndef FORTRAN_headername_H_
|
||||
#define FORTRAN_headername_H_
|
||||
// code
|
||||
#endif // FORTRAN_headername_H_
|
||||
|
||||
Use // for all comments except for short /*notes*/ within statements.
|
||||
When // follows code on a line, precede it with two spaces. Comments
|
||||
should matter. Assume that the reader knows current C++ at least as
|
||||
well as you do and avoid distracting her by calling out usage of new
|
||||
features in comments.
|
||||
|
||||
Use {braced initializers} in all circumstances where they work, including
|
||||
default data member initialization. They inhibit implicit truncation.
|
||||
Don't use "= expr" initialization just to effect implicit truncation;
|
||||
prefer an explicit static_cast<>.
|
||||
|
||||
Avoid unsigned types apart from size_t, which must be used with care.
|
||||
When int just obviously works, just use int. When you need something bigger
|
||||
than int, use std::int64_t.
|
||||
|
||||
Never throw or catch exceptions.
|
||||
Never use run-time type information or dynamic_cast<>.
|
||||
Never declare static data that executes a constructor.
|
||||
|
||||
Indent with two spaces, except for public:/protected:/private: in classes,
|
||||
which are indented by one. Never use more than 80 characters per source line.
|
||||
Don't use tabs. Don't try to make columns of variable names or comments
|
||||
align vertically -- they are maintenance problems. Don't indent the bodies
|
||||
of namespaces, even when nested.
|
||||
|
||||
Define accessor and mutator member functions (implicitly) inline in the
|
||||
class, after constructors and assignments. Don't needlessly define
|
||||
(implicit) inline member functions in classes unless they really solve a
|
||||
performance problem. Try to make class definitions in headers concise
|
||||
specifications of interfaces, at least to the degree that C++ allows.
|
||||
|
||||
#include header that a project header or source file actually uses directly.
|
||||
(Exception: when foo.cc starts with #include "foo.h", and foo.h includes
|
||||
bar.h in order to define the interface to foo, you don't have to redundantly
|
||||
include bar.h in foo.cc.) Order the #include directives for foo.cc as
|
||||
|
||||
#include "foo.h" // this module's interface comes first
|
||||
#include "armadillo.h" // other modules in this project, alphabetically
|
||||
#include "zebra.h"
|
||||
#include <algorithm> // C++ standard headers, alphabetically
|
||||
#include <vector>
|
||||
#include <sys/types.h> // C headers, alphabetically
|
||||
|
||||
Put templates into headers when they need to be there.
|
||||
Prefer static functions to functions in anonymous namespaces in source files.
|
||||
|
||||
Use namespaces to avoid conflicts with client code. Use one top-level project
|
||||
namespace. Don't introduce needless nested namespaces within a project
|
||||
when names don't conflict or better solutions exist. Never use
|
||||
"using namespace ...;", especially not "using namespace std;". Access
|
||||
STL entities with names like "std::unique_ptr<>", without a leading "::".
|
||||
|
||||
Don't waste space on the screen with needless blank lines or elaborate block
|
||||
commentary (lines of dashes, boxes of asterisks, &c.). Write code so as to be
|
||||
easily read and understood with a minimum of scrolling. Function result types
|
||||
go on the same line as the function and argument names, if they can all fit
|
||||
in 80 columns.
|
||||
|
||||
It is fine to use short names for local variables with limited scopes,
|
||||
especially when you can declare them directly in the for()/while()/if()
|
||||
condition. Otherwise, prefer complete English words to abbreviations
|
||||
when creating names.
|
||||
|
||||
Use "auto" judiciously. When the type of a local variable is known and
|
||||
easy to type, be explicit rather than using auto.
|
||||
|
||||
Use move semantics and smart pointers to make dynamic memory ownership
|
||||
clear. Consider reworking any code that uses malloc() or a (non-placement)
|
||||
operator new. When copy constructors and copy assignment are not necessary,
|
||||
and move constructors/assignment is present, don't declare them and they
|
||||
will be implicitly "= delete;". When neither copy nor move constructors
|
||||
or assignments should exist for a class, explicitly "= delete;" all of them.
|
||||
|
||||
Use references for const arguments; prefer const references to values for
|
||||
all but small types that are trivially copyable (e.g., int). Use non-const
|
||||
pointers for output arguments. Put output arguments last (pace the standard
|
||||
C library conventions for memcpy() & al.).
|
||||
|
||||
Prefer "template<typename T>" to "template<class T>".
|
||||
|
||||
Prefer "enum class" to plain "enum" wherever enum class will work.
|
||||
|
||||
Use constexpr and const generously.
|
||||
|
||||
Always wrap the bodies of if(), else, while(), for(), do, &c. with braces,
|
||||
even when the body is a single statement or empty. The opening "{" goes on
|
||||
the end of the line, not on the next line. Functions also put the opening
|
||||
"{" after the formal arguments or new-style result type, not on the next
|
||||
line. Use "{}" for empty inline constructors and destructors in classes.
|
||||
|
||||
Don't use dynamic solutions to solve problems that can be solved at
|
||||
build time; don't solve build time problems by writing programs that
|
||||
produce source code when macros and templates suffice; don't write macros
|
||||
when templates suffice. Templates are statically typed, checked by the
|
||||
compiler, and visible to debuggers.
|
||||
|
||||
When a switch() does not cover all case values explicitly, it should
|
||||
contains either a "default:;" at its end or a "default:" label that
|
||||
crashes.
|
Loading…
Reference in New Issue