* Completely remove inline namespace v2 * Flatten some unnecessarily deep namespace nesting * Move DummyClientFace, Segmenter, SegmentFetcher to namespace ndn * Move all unit tests to namespace ndn::tests Change-Id: I8bcfcf9fd669936a3277d2d5d505f765b4b05742
1095 lines
31 KiB
ReStructuredText
1095 lines
31 KiB
ReStructuredText
ndn-cxx Code Style and Coding Guidelines
|
|
========================================
|
|
|
|
Based on
|
|
|
|
* "C++ Programming Style Guidelines" by Geotechnical Software Services, Copyright © 1996-2011.
|
|
The original document is available at `<http://geosoft.no/development/cppstyle.html>`__
|
|
|
|
* NDN Platform "C++, C, C#, Java and JavaScript Code Guidelines".
|
|
The original document is available at `<https://named-data.net/codebase/platform/documentation/ndn-platform-development-guidelines/cpp-code-guidelines/>`__
|
|
|
|
1. Code layout
|
|
--------------
|
|
|
|
1.1. The code layout should generally follow the GNU coding standard layout for C,
|
|
extended it to C++.
|
|
|
|
* Do not use tabs for indentation.
|
|
* Indentation spacing is 2 spaces.
|
|
* Lines should be within a reasonable range. Lines longer than 100 columns should
|
|
generally be avoided.
|
|
|
|
1.2. Whitespace
|
|
|
|
* Conventional operators (``if``, ``for``, ``while``, and others) should be
|
|
surrounded by a space character.
|
|
* Commas should be followed by a white space.
|
|
* Semicolons in for statments should be followed by a space character.
|
|
|
|
Examples:
|
|
|
|
.. code-block:: c++
|
|
|
|
a = (b + c) * d; // NOT: a=(b+c)*d
|
|
|
|
while (true) { // NOT: while(true)
|
|
...
|
|
|
|
doSomething(a, b, c, d); // NOT: doSomething(a,b,c,d);
|
|
|
|
for (i = 0; i < 10; i++) { // NOT: for(i=0;i<10;i++){
|
|
...
|
|
|
|
1.3. Namespaces should have the following form:
|
|
|
|
.. code-block:: c++
|
|
|
|
namespace example {
|
|
|
|
code;
|
|
moreCode;
|
|
|
|
} // namespace example
|
|
|
|
Note that code inside the namespace is **not** indented. Avoid the following:
|
|
|
|
.. code-block:: c++
|
|
|
|
// WRONG
|
|
//
|
|
// namespace example {
|
|
//
|
|
// code;
|
|
// moreCode;
|
|
//
|
|
// } // namespace example
|
|
|
|
1.4. Class declarations should have the following form:
|
|
|
|
.. code-block:: c++
|
|
|
|
class SomeClass : public BaseClass
|
|
{
|
|
public:
|
|
... <public methods> ...
|
|
|
|
protected:
|
|
... <protected methods> ...
|
|
|
|
private:
|
|
... <private methods> ...
|
|
|
|
public:
|
|
... <public data> ...
|
|
|
|
protected:
|
|
... <protected data> ...
|
|
|
|
private:
|
|
... <private data> ...
|
|
};
|
|
|
|
``public``, ``protected``, ``private`` may be repeated several times without
|
|
interleaving (e.g., public, public, public, private, private) if this improves
|
|
readability of the code.
|
|
|
|
Nested classes can be defined in appropriate visibility section, either in methods
|
|
block, data block, or in a separate section (depending which one provides better code
|
|
readability).
|
|
|
|
1.5. Method and function definitions should have the following form:
|
|
|
|
.. code-block:: c++
|
|
|
|
void
|
|
someMethod()
|
|
{
|
|
...
|
|
}
|
|
|
|
void
|
|
SomeClass::someMethod()
|
|
{
|
|
...
|
|
}
|
|
|
|
1.6. The ``if-else`` class of statements should have the following form:
|
|
|
|
.. code-block:: c++
|
|
|
|
if (condition) {
|
|
statements;
|
|
}
|
|
|
|
if (condition) {
|
|
statements;
|
|
}
|
|
else {
|
|
statements;
|
|
}
|
|
|
|
if (condition) {
|
|
statements;
|
|
}
|
|
else if (condition) {
|
|
statements;
|
|
}
|
|
else {
|
|
statements;
|
|
}
|
|
|
|
1.7. A ``for`` statement should have the following form:
|
|
|
|
.. code-block:: c++
|
|
|
|
for (initialization; condition; update) {
|
|
statements;
|
|
}
|
|
|
|
An empty ``for`` statement should have the following form:
|
|
|
|
.. code-block:: c++
|
|
|
|
for (initialization; condition; update)
|
|
;
|
|
|
|
This emphasizes the fact that the ``for`` statement is empty and makes it obvious for
|
|
the reader that this is intentional. Empty loops should be avoided however.
|
|
|
|
1.8. A ``while`` statement should have the following form:
|
|
|
|
.. code-block:: c++
|
|
|
|
while (condition) {
|
|
statements;
|
|
}
|
|
|
|
1.9. A ``do-while`` statement should have the following form:
|
|
|
|
.. code-block:: c++
|
|
|
|
do {
|
|
statements;
|
|
} while (condition);
|
|
|
|
1.10. A ``switch`` statement should have the following form:
|
|
|
|
.. code-block:: c++
|
|
|
|
switch (condition) {
|
|
case ABC: // 2 space indent
|
|
statements; // 4 space indent
|
|
[[fallthrough]];
|
|
|
|
case DEF:
|
|
statements;
|
|
break;
|
|
|
|
case XYZ: {
|
|
statements;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
statements;
|
|
break;
|
|
}
|
|
|
|
When curly braces are used inside a ``case`` block, the braces must cover the entire
|
|
``case`` block.
|
|
|
|
.. code-block:: c++
|
|
|
|
switch (condition) {
|
|
// Correct style
|
|
case A0: {
|
|
statements;
|
|
break;
|
|
}
|
|
|
|
// Correct style
|
|
case A1: {
|
|
statements;
|
|
[[fallthrough]];
|
|
}
|
|
|
|
// Incorrect style: braces should cover the entire case block
|
|
case B: {
|
|
statements;
|
|
}
|
|
statements;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
The following style is still allowed when none of the ``case`` blocks has curly braces.
|
|
|
|
.. code-block:: c++
|
|
|
|
switch (condition) {
|
|
case ABC: // no indent
|
|
statements; // 2 space indent
|
|
[[fallthrough]];
|
|
|
|
case DEF:
|
|
statements;
|
|
break;
|
|
|
|
default:
|
|
statements;
|
|
break;
|
|
}
|
|
|
|
The ``[[fallthrough]]`` annotation must be included whenever there is a
|
|
case without a break statement. Leaving the break out is a common error,
|
|
and it must be made clear that it is intentional when it is not there.
|
|
Moreover, modern compilers will warn when a case that falls through is
|
|
not explicitly annotated.
|
|
|
|
1.11. A ``try-catch`` statement should have the following form:
|
|
|
|
.. code-block:: c++
|
|
|
|
try {
|
|
statements;
|
|
}
|
|
catch (const Exception& exception) {
|
|
statements;
|
|
}
|
|
|
|
1.12. The incompleteness of split lines must be made obvious.
|
|
|
|
.. code-block:: c++
|
|
|
|
totalSum = a + b + c +
|
|
d + e;
|
|
function(param1, param2,
|
|
param3);
|
|
for (int tableNo = 0; tableNo < nTables;
|
|
tableNo += tableStep) {
|
|
...
|
|
}
|
|
|
|
Split lines occur when a statement exceeds the column limit given in rule 1.1. It is
|
|
difficult to give rigid rules for how lines should be split, but the examples above should
|
|
give a general hint. In general:
|
|
|
|
* Break after a comma.
|
|
* Break after an operator.
|
|
* Align the new line with the beginning of the expression on the previous line.
|
|
|
|
Exceptions:
|
|
|
|
* The following is standard practice with ``operator<<``:
|
|
|
|
.. code-block:: c++
|
|
|
|
std::cout << "Something here "
|
|
<< "Something there" << std::endl;
|
|
|
|
1.13. When class variables need to be initialized in the constructor, the initialization
|
|
should take the following form:
|
|
|
|
.. code-block:: c++
|
|
|
|
SomeClass::SomeClass(int value, const std::string& string)
|
|
: m_value(value)
|
|
, m_string(string)
|
|
...
|
|
{
|
|
}
|
|
|
|
Each initialization should be put on a separate line, starting either with the colon
|
|
for the first initialization or with comma for all subsequent initializations.
|
|
|
|
1.14. A range-based ``for`` statement should have the following form:
|
|
|
|
.. code-block:: c++
|
|
|
|
for (T i : range) {
|
|
statements;
|
|
}
|
|
|
|
1.15. A lambda expression should have the following form:
|
|
|
|
.. code-block:: c++
|
|
|
|
[&capture1, capture2] (T1 arg1, T2 arg2) {
|
|
statements;
|
|
}
|
|
|
|
[&capture1, capture2] (T1 arg1, T2 arg2) mutable {
|
|
statements;
|
|
}
|
|
|
|
[this] (T arg) {
|
|
statements;
|
|
}
|
|
|
|
[&] (T arg) {
|
|
statements;
|
|
}
|
|
|
|
[=] (T arg) {
|
|
statements;
|
|
}
|
|
|
|
If the lambda has no parameters, ``()`` should be omitted.
|
|
|
|
.. code-block:: c++
|
|
|
|
[&capture1, capture2] {
|
|
statements;
|
|
}
|
|
|
|
Trailing return types should be omitted whenever possible. Add it only when the compiler
|
|
cannot deduce the return type automatically, or when it improves readability. Note that
|
|
``()`` is required by the C++ standard when ``mutable`` or a trailing return type is used.
|
|
|
|
.. code-block:: c++
|
|
|
|
[] (T arg) -> int {
|
|
statements;
|
|
}
|
|
|
|
[] () -> int {
|
|
statements;
|
|
}
|
|
|
|
If the function body has only one line, and the whole lambda expression can fit in one line,
|
|
the following form is also acceptable:
|
|
|
|
.. code-block:: c++
|
|
|
|
[&capture1, capture2] (T1 arg1, T2 arg2) { statement; }
|
|
|
|
A no-op lambda can be written in a more compact form:
|
|
|
|
.. code-block:: c++
|
|
|
|
[]{}
|
|
|
|
1.16. List initialization should have the following form:
|
|
|
|
.. code-block:: c++
|
|
|
|
T object{arg1, arg2};
|
|
|
|
T{arg1, arg2};
|
|
|
|
new T{arg1, arg2};
|
|
|
|
return {arg1, arg2};
|
|
|
|
function({arg1, arg2}, otherArgument);
|
|
|
|
object[{arg1, arg2}];
|
|
|
|
T({arg1, arg2})
|
|
|
|
T object = {arg1, arg2};
|
|
|
|
class Class
|
|
{
|
|
private:
|
|
T m_member{arg1, arg2};
|
|
static T s_member = {arg1, arg2};
|
|
};
|
|
|
|
An empty braced-init-list is written as ``{}``. For example:
|
|
|
|
.. code-block:: c++
|
|
|
|
T object{};
|
|
T object = {};
|
|
|
|
2. Naming Conventions
|
|
---------------------
|
|
|
|
2.1. C++ header files should have the extension ``.hpp``. Source files should have the
|
|
extension ``.cpp``
|
|
|
|
File names should be all lower case. If the class name
|
|
is a composite of several words, each word in a file name should be separated with a
|
|
dash (-). A class should be declared in a header file and defined in a source file
|
|
where the name of the files match the name of the class.
|
|
|
|
::
|
|
|
|
my-class.hpp, my-class.cpp
|
|
|
|
2.2. Names representing types must be written in English in mixed case starting with upper case.
|
|
|
|
.. code-block:: c++
|
|
|
|
class MyClass;
|
|
class Line;
|
|
class SavingsAccount;
|
|
|
|
2.3. Variable names must be written in English in mixed case starting with lower case.
|
|
|
|
.. code-block:: c++
|
|
|
|
MyClass myClass;
|
|
Line line;
|
|
SavingsAccount savingsAccount;
|
|
int theAnswerToLifeTheUniverseAndEverything;
|
|
|
|
2.4. Named constants (including enumeration values) must be all uppercase using underscore
|
|
to separate words.
|
|
|
|
.. code-block:: c++
|
|
|
|
const int MAX_ITERATIONS = 25;
|
|
const std::string COLOR_RED = "red";
|
|
static const double PI = 3.14;
|
|
|
|
In some cases, it is a better (or is the only way for complex constants in header-only
|
|
classes) to implement the value as a method.
|
|
|
|
.. code-block:: c++
|
|
|
|
static int // declare constexpr if possible
|
|
getMaxIterations()
|
|
{
|
|
return 25;
|
|
}
|
|
|
|
2.5. Names representing methods or functions must be commands starting with a verb and
|
|
written in mixed case starting with lower case.
|
|
|
|
.. code-block:: c++
|
|
|
|
std::string
|
|
getName()
|
|
{
|
|
...
|
|
}
|
|
|
|
double
|
|
computeTotalWidth()
|
|
{
|
|
...
|
|
}
|
|
|
|
2.6. Names representing namespaces should be all lowercase.
|
|
|
|
.. code-block:: c++
|
|
|
|
namespace model::analyzer {
|
|
|
|
...
|
|
|
|
} // namespace model::analyzer
|
|
|
|
2.7. Names representing generic template types should be a single uppercase letter.
|
|
|
|
.. code-block:: c++
|
|
|
|
template<class T> ...
|
|
template<class C, class D> ...
|
|
|
|
However, when a template parameter represents a certain concept and is expected
|
|
to have a certain interface, the name should be explicitly spelled out.
|
|
|
|
.. code-block:: c++
|
|
|
|
template<class InputIterator> ...
|
|
template<class Packet> ...
|
|
|
|
2.8. Abbreviations and acronyms must not be uppercase when used as name.
|
|
|
|
.. code-block:: c++
|
|
|
|
exportHtmlSource(); // NOT: exportHTMLSource();
|
|
openDvdPlayer(); // NOT: openDVDPlayer();
|
|
|
|
2.9. Global variables should have ``g_`` prefix
|
|
|
|
.. code-block:: c++
|
|
|
|
g_mainWindow.open();
|
|
g_applicationContext.getName();
|
|
|
|
In general, the use of global variables should be avoided. Consider using singleton
|
|
objects instead.
|
|
|
|
2.10. All non-static data members of a class should be prefixed with ``m_`` unless they
|
|
are public. Similarly, non-public static data members should be prefixed with ``s_``.
|
|
|
|
.. code-block:: c++
|
|
|
|
class SomeClass
|
|
{
|
|
private:
|
|
int m_length;
|
|
|
|
static std::string s_name;
|
|
};
|
|
|
|
2.11. Variables with a large scope should have long (explicit) names, variables with a small
|
|
scope can have short names.
|
|
|
|
Scratch variables used for temporary storage or indices are best kept short. A
|
|
programmer reading such variables should be able to assume that its value is not used
|
|
outside of a few lines of code. Common scratch variables for integers are ``i``,
|
|
``j``, ``k``, ``m``, ``n`` and for characters ``c`` and ``d``.
|
|
|
|
2.12. The name of the object is implicit, and should be avoided in a method name.
|
|
|
|
.. code-block:: c++
|
|
|
|
line.getLength(); // NOT: line.getLineLength();
|
|
|
|
The latter seems natural in the class declaration, but proves superfluous in use, as
|
|
shown in the example.
|
|
|
|
2.13. The terms ``get/set`` must be used where an attribute is accessed directly.
|
|
|
|
.. code-block:: c++
|
|
|
|
employee.getName();
|
|
employee.setName(name);
|
|
|
|
matrix.getElement(2, 4);
|
|
matrix.setElement(2, 4, value);
|
|
|
|
2.14. The term ``compute`` can be used in methods where something is computed.
|
|
|
|
.. code-block:: c++
|
|
|
|
valueSet.computeAverage();
|
|
matrix.computeInverse()
|
|
|
|
Give the reader the immediate clue that this is a potentially time-consuming operation,
|
|
and if used repeatedly, he might consider caching the result. Consistent use of the term
|
|
enhances readability.
|
|
|
|
2.15. The term ``find`` can be used in methods where something is looked up.
|
|
|
|
.. code-block:: c++
|
|
|
|
vertex.findNearestVertex();
|
|
matrix.findMinElement();
|
|
|
|
Give the reader the immediate clue that this is a simple look up method with a minimum
|
|
of computations involved. Consistent use of the term enhances readability.
|
|
|
|
2.16. Plural form should be used on names representing a collection of objects.
|
|
|
|
.. code-block:: c++
|
|
|
|
vector<Point> points;
|
|
int values[];
|
|
|
|
Enhances readability since the name gives the user an immediate clue of the type of
|
|
the variable and the operations that can be performed on its elements.
|
|
|
|
2.17. The prefix ``n`` should be used for variables representing a number of objects.
|
|
|
|
.. code-block:: c++
|
|
|
|
nPoints, nLines
|
|
|
|
The notation is taken from mathematics where it is an established convention for
|
|
indicating a number of objects.
|
|
|
|
2.18. The suffix ``Num`` or ``No`` should be used for variables representing an entity number.
|
|
|
|
.. code-block:: c++
|
|
|
|
tableNum, tableNo, employeeNum, employeeNo
|
|
|
|
2.19. The prefix ``is``, ``has``, ``need``, or similar should be used for boolean variables and
|
|
methods.
|
|
|
|
.. code-block:: c++
|
|
|
|
isSet, isVisible, isFinished, isFound, isOpen
|
|
needToConvert, needToFinish
|
|
|
|
2.20. Complement names must be used for complement operations, reducing complexity by
|
|
symmetry.
|
|
|
|
::
|
|
|
|
get/set, add/remove, create/destroy, start/stop, insert/erase,
|
|
increment/decrement, old/new, begin/end, first/last, up/down, min/max,
|
|
next/previous (and commonly used next/prev), open/close, show/hide,
|
|
suspend/resume, etc.
|
|
|
|
The pair ``insert/erase`` is preferred. ``insert/delete`` can also be used if it
|
|
does not conflict with the ``delete`` keyword of C++.
|
|
|
|
2.21. Variable names should not include reference to variable type (do not use Hungarian
|
|
notation).
|
|
|
|
.. code-block:: c++
|
|
|
|
Line* line; // NOT: Line* pLine;
|
|
// NOT: Line* linePtr;
|
|
|
|
size_t nPoints; // NOT lnPoints
|
|
|
|
char* name; // NOT szName
|
|
|
|
2.22. Negated boolean variable names should be avoided.
|
|
|
|
.. code-block:: c++
|
|
|
|
bool isError; // NOT: isNoError
|
|
bool isFound; // NOT: isNotFound
|
|
|
|
2.23. Enumeration constants recommended to prefix with a common type name.
|
|
|
|
.. code-block:: c++
|
|
|
|
enum Color {
|
|
COLOR_RED,
|
|
COLOR_GREEN,
|
|
COLOR_BLUE
|
|
};
|
|
|
|
2.24. Exceptions can be suffixed with either ``Exception`` (e.g., ``SecurityException``) or
|
|
``Error`` (e.g., ``SecurityError``).
|
|
|
|
The recommended method is to declare an exception class ``Exception`` or ``Error`` as
|
|
a nested type inside the class from which the exception is thrown. For example, when
|
|
defining a class ``Foo`` that can throw errors, one can write the following:
|
|
|
|
.. code-block:: c++
|
|
|
|
#include <stdexcept>
|
|
|
|
class Foo
|
|
{
|
|
public:
|
|
class Error : public std::runtime_error
|
|
{
|
|
public:
|
|
// You can inherit constructors from std::runtime_error like this:
|
|
using std::runtime_error::runtime_error;
|
|
|
|
// Additional constructors, if desired, can be declared as usual:
|
|
Error(const std::string& what, const std::exception& inner)
|
|
: std::runtime_error(what + ": " + inner.what())
|
|
{
|
|
}
|
|
};
|
|
};
|
|
|
|
In addition to that, if class Foo is a base class or interface for some class
|
|
hierarchy, then child classes should should define their own ``Error`` or
|
|
``Exception`` classes that are inherited from the parent's Error class.
|
|
|
|
2.25. Functions (methods returning something) should be named after what they return and
|
|
procedures (void methods) after what they do.
|
|
|
|
Increase readability. Makes it clear what the unit should do and especially all the
|
|
things it is not supposed to do. This again makes it easier to keep the code clean of
|
|
side effects.
|
|
|
|
3. Miscellaneous
|
|
----------------
|
|
|
|
3.1. Exceptions can be used in the code, but should be used only in exceptional cases and
|
|
not in the primary processing path.
|
|
|
|
3.2. Header files must contain an include guard.
|
|
|
|
For example, a header file named ``module/class-name.hpp`` or
|
|
``src/module/class-name.hpp`` should have a header guard in the following form:
|
|
|
|
.. code-block:: c++
|
|
|
|
#ifndef APP_MODULE_CLASS_NAME_HPP
|
|
#define APP_MODULE_CLASS_NAME_HPP
|
|
...
|
|
#endif // APP_MODULE_CLASS_NAME_HPP
|
|
|
|
The macro name should reflect the path of the header file relative to the root of the
|
|
source tree, in order to prevent naming conflicts. The header guard should be prefixed
|
|
with the application/library name to avoid conflicts with other packages and libraries.
|
|
|
|
3.3. Include directives for system headers and other external libraries should use
|
|
``<angle brackets>``. Header files in the same source code repository should be included
|
|
using ``"quotes"``.
|
|
|
|
.. code-block:: c++
|
|
|
|
#include "ndn-cxx/util/random.hpp"
|
|
|
|
#include <string>
|
|
#include <boost/lexical_cast.hpp>
|
|
|
|
All of a project's header files should be included with their path relative to
|
|
the project's source directory. The use of UNIX directory shortcuts ``.``
|
|
(the current directory) and ``..`` (the parent directory) is discouraged.
|
|
|
|
3.4. Include statements should be grouped. Same-project headers should be included first.
|
|
Leave an empty line between groups of include statements. Sort alphabetically within a group.
|
|
For example, the include section of ``ndn-cxx/foo/bar.cpp`` may look like this:
|
|
|
|
.. code-block:: c++
|
|
|
|
#include "ndn-cxx/impl/pending-interest.hpp"
|
|
#include "ndn-cxx/util/random.hpp"
|
|
|
|
#include <cstdlib>
|
|
#include <fstream>
|
|
#include <iomanip>
|
|
|
|
#include <boost/lexical_cast.hpp>
|
|
#include <boost/regex.hpp>
|
|
|
|
3.5. Definitions that are local to only one ``.cpp`` file should be declared inside that
|
|
file and be placed in an unnamed namespace or declared ``static``.
|
|
|
|
3.6. Implicit conversion is generally allowed.
|
|
|
|
Implicit conversion between integer and floating point numbers can cause problems and
|
|
should be avoided.
|
|
|
|
Implicit conversion in constructors that can be called with a single argument is usually
|
|
undesirable. Therefore, all single-argument constructors should be marked ``explicit``,
|
|
unless implicit conversion is desirable. In that case, a comment should document the
|
|
reason for this.
|
|
As an exception, copy and move constructors should not be explicit, since they do not
|
|
perform type conversion.
|
|
Constructors that cannot be called with a single argument may omit ``explicit``.
|
|
Constructors that take a single ``std::initializer_list`` parameter should also omit
|
|
``explicit``, in order to support copy-initialization.
|
|
|
|
Avoid C-style casts.
|
|
Use ``static_cast``, ``dynamic_cast``, ``const_cast``, ``reinterpret_cast``, or
|
|
``bit_cast`` instead where appropriate.
|
|
Use ``static_pointer_cast``, ``dynamic_pointer_cast``, or ``const_pointer_cast``
|
|
when dealing with ``shared_ptr``.
|
|
|
|
3.7. Variables should be initialized where they are declared.
|
|
|
|
This ensures that variables are valid at any time. Sometimes it is impossible to
|
|
initialize a variable to a valid value where it is declared.
|
|
|
|
.. code-block:: c++
|
|
|
|
int x, y, z;
|
|
getCenter(&x, &y, &z);
|
|
|
|
In these cases it should be left uninitialized rather than initialized to some phony
|
|
value.
|
|
|
|
3.8. In most cases, class data members should not be declared ``public``.
|
|
|
|
Public data members violate the concepts of information hiding and encapsulation.
|
|
Use private variables and public accessor methods instead.
|
|
|
|
Exceptions to this rule:
|
|
|
|
* When the class is essentially a passive data structure with no or minimal behavior
|
|
(equivalent to a C struct, also known as POD type). In this case, all fields should
|
|
be public and the keyword ``struct`` should be used instead of ``class``.
|
|
|
|
* When the class is used only inside the compilation unit, e.g., when implementing pImpl
|
|
idiom (aka Bridge pattern) or similar cases.
|
|
|
|
3.9. C++ pointers and references should have their reference symbol next to the type rather
|
|
than to the name.
|
|
|
|
.. code-block:: c++
|
|
|
|
float* x; // NOT: float *x;
|
|
int& y; // NOT: int &y;
|
|
|
|
3.10. Implicit test for 0 should not be used other than for boolean variables and pointers.
|
|
|
|
.. code-block:: c++
|
|
|
|
if (nLines != 0) // NOT: if (nLines)
|
|
|
|
int* ptr = ...
|
|
if (ptr) // OK
|
|
if (ptr != nullptr) // also OK
|
|
|
|
3.11. *(removed)*
|
|
|
|
3.12. Loop variables should be initialized immediately before the loop.
|
|
|
|
.. code-block:: c++
|
|
|
|
bool isDone = false; // NOT: bool isDone = false;
|
|
while (!isDone) { // // other stuff
|
|
... // while (!isDone) {
|
|
} // ...
|
|
// }
|
|
|
|
3.13. The form ``while (true)`` should be used for infinite loops.
|
|
|
|
.. code-block:: c++
|
|
|
|
while (true) {
|
|
...
|
|
}
|
|
|
|
// NOT:
|
|
for (;;) { // NO!
|
|
...
|
|
}
|
|
while (1) { // NO!
|
|
...
|
|
}
|
|
|
|
3.14. Complex conditional expressions must be avoided. Introduce temporary boolean variables
|
|
instead.
|
|
|
|
.. code-block:: c++
|
|
|
|
bool isFinished = (elementNo < 0) || (elementNo > maxElement);
|
|
bool isRepeatedEntry = elementNo == lastElement;
|
|
if (isFinished || isRepeatedEntry) {
|
|
...
|
|
}
|
|
|
|
// NOT:
|
|
// if ((elementNo < 0) || (elementNo > maxElement) || elementNo == lastElement) {
|
|
// ...
|
|
// }
|
|
|
|
By assigning boolean variables to expressions, the program gets automatic
|
|
documentation. The construction will be easier to read, debug, and maintain.
|
|
|
|
3.15. The conditional should be put on a separate line.
|
|
|
|
.. code-block:: c++
|
|
|
|
if (isDone) // NOT: if (isDone) doCleanup();
|
|
doCleanup();
|
|
|
|
This is for debugging purposes. When writing on a single line, it is not apparent
|
|
whether the test is really true or not.
|
|
|
|
3.16. Assignment statements in conditionals must be avoided.
|
|
|
|
.. code-block:: c++
|
|
|
|
File* fileHandle = open(fileName, "w");
|
|
if (!fileHandle) {
|
|
...
|
|
}
|
|
|
|
// NOT
|
|
// if (!(fileHandle = open(fileName, "w"))) {
|
|
// ..
|
|
// }
|
|
|
|
3.17. The use of magic numbers in the code should be avoided. Numbers other than 0 and 1
|
|
should be considered declared as named constants instead.
|
|
|
|
If the number does not have an obvious meaning by itself, the readability is enhanced
|
|
by introducing a named constant instead. A different approach is to introduce a method
|
|
from which the constant can be accessed.
|
|
|
|
3.18. Floating point literals should always be written with a decimal point, at least one
|
|
decimal, and without omitting 0 before the decimal point.
|
|
|
|
.. code-block:: c++
|
|
|
|
double total = 0.0; // NOT: double total = 0;
|
|
double someValue = 0.1; // NOT double someValue = .1;
|
|
double speed = 3.0e8; // NOT: double speed = 3e8;
|
|
double sum;
|
|
...
|
|
sum = (a + b) * 10.0;
|
|
|
|
3.19. ``goto`` should not be used.
|
|
|
|
``goto`` statements violate the idea of structured code. Only in very few cases (for
|
|
instance, breaking out of deeply nested structures) should ``goto`` be considered,
|
|
and only if the alternative structured counterpart is proven to be less readable.
|
|
|
|
3.20. ``nullptr`` should be used to represent a null pointer, instead of "0" or "NULL".
|
|
|
|
3.21. Logical units within a block should be separated by one blank line.
|
|
|
|
.. code-block:: c++
|
|
|
|
Matrix4x4 matrix = new Matrix4x4();
|
|
|
|
double cosAngle = Math.cos(angle);
|
|
double sinAngle = Math.sin(angle);
|
|
|
|
matrix.setElement(1, 1, cosAngle);
|
|
matrix.setElement(1, 2, sinAngle);
|
|
matrix.setElement(2, 1, -sinAngle);
|
|
matrix.setElement(2, 2, cosAngle);
|
|
|
|
multiply(matrix);
|
|
|
|
Enhance readability by introducing white space between logical units of a block.
|
|
|
|
3.22. Variables in declarations can be left aligned.
|
|
|
|
.. code-block:: c++
|
|
|
|
AsciiFile* file;
|
|
int nPoints;
|
|
float x, y;
|
|
|
|
Enhance readability. The variables are easier to spot from the types by alignment.
|
|
|
|
3.23. Use alignment wherever it enhances readability.
|
|
|
|
.. code-block:: c++
|
|
|
|
value = (potential * oilDensity) / constant1 +
|
|
(depth * waterDensity) / constant2 +
|
|
(zCoordinateValue * gasDensity) / constant3;
|
|
|
|
minPosition = computeDistance(min, x, y, z);
|
|
averagePosition = computeDistance(average, x, y, z);
|
|
|
|
There are a number of places in the code where white space can be included to enhance
|
|
readability even if this violates common guidelines. Many of these cases have to do
|
|
with code alignment. General guidelines on code alignment are difficult to give, but
|
|
the examples above should give a general clue.
|
|
|
|
3.24. All comments should be written in English.
|
|
|
|
In an international environment, English is the preferred language.
|
|
|
|
3.25. Use ``//`` for all comments, including multi-line comments.
|
|
|
|
.. code-block:: c++
|
|
|
|
// Comment spanning
|
|
// more than one line.
|
|
|
|
Since multilevel C-commenting is not supported, using ``//`` comments ensure that it
|
|
is always possible to comment out entire sections of a file using ``/* */`` for
|
|
debugging purposes etc.
|
|
|
|
There should be a space between the ``//`` and the actual comment, and comments should
|
|
always start with an upper case letter and end with a period.
|
|
|
|
However, method and class documentation comments should use ``/** */`` style for
|
|
Doxygen, JavaDoc and JSDoc. License boilerplate should use ``/* */`` style.
|
|
|
|
3.26. Comments should be included relative to their position in the code.
|
|
|
|
.. code-block:: c++
|
|
|
|
while (true) {
|
|
// Do something
|
|
something();
|
|
}
|
|
|
|
// NOT:
|
|
while (true) {
|
|
// Do something
|
|
something();
|
|
}
|
|
|
|
This is to avoid that the comments break the logical structure of the program.
|
|
|
|
3.27. Use ``BOOST_ASSERT`` and ``BOOST_ASSERT_MSG`` for runtime assertions.
|
|
|
|
.. code-block:: c++
|
|
|
|
int x = 1;
|
|
int y = 2;
|
|
int z = x + y;
|
|
BOOST_ASSERT(z - y == x);
|
|
|
|
The expression passed to ``BOOST_ASSERT`` must not have side effects,
|
|
because it may not be evaluated in release builds.
|
|
|
|
3.28. Use ``static_assert`` for compile-time assertions.
|
|
|
|
.. code-block:: c++
|
|
|
|
class BaseClass
|
|
{
|
|
};
|
|
|
|
class DerivedClass : public BaseClass
|
|
{
|
|
};
|
|
|
|
static_assert(std::is_base_of<BaseClass, DerivedClass>::value,
|
|
"DerivedClass must inherit from BaseClass");
|
|
|
|
3.29. The ``auto`` type specifier may be used for local variables if a human reader can
|
|
easily deduce the actual type, or if it makes the code safer.
|
|
|
|
.. code-block:: c++
|
|
|
|
std::vector<int> intVector;
|
|
auto i = intVector.find(4); // OK
|
|
|
|
auto stringSet = std::make_shared<std::set<std::string>>(); // OK
|
|
|
|
std::vector<std::string> strings;
|
|
for (const auto& str : strings) { // OK, iterating over the elements of a container
|
|
std::cout << str;
|
|
}
|
|
|
|
obj.onEvent([] (auto&&...) { std::cout << "hi!"; }); // OK, unused lambda parameters
|
|
|
|
auto x = foo(); // BAD unless foo() is declared nearby or has a well-known prototype
|
|
|
|
3.30. Use the ``override`` or ``final`` specifier when overriding a virtual
|
|
member function or a virtual destructor.
|
|
|
|
``virtual`` must not be used along with ``final`` so that the compiler can generate
|
|
an error when a final function does not override.
|
|
|
|
``virtual`` should not be used along with ``override`` for consistency with ``final``.
|
|
|
|
.. code-block:: c++
|
|
|
|
class Stream
|
|
{
|
|
public:
|
|
virtual void
|
|
open();
|
|
};
|
|
|
|
class InputStream : public Stream
|
|
{
|
|
public:
|
|
void
|
|
open() override;
|
|
};
|
|
|
|
class Console : public InputStream
|
|
{
|
|
public:
|
|
void
|
|
open() final;
|
|
};
|
|
|
|
3.31. The recommended way to throw an exception derived from ``std::exception`` is to use
|
|
``NDN_THROW`` or one of the other ``NDN_THROW_*`` macros.
|
|
|
|
Exceptions thrown using these macros will be augmented with additional diagnostic
|
|
information, including the file name, line number, and function name from which
|
|
the exception was thrown.
|
|
|
|
The extended diagnostic information contained in the exception can be printed with
|
|
``boost::diagnostic_information()``.
|
|
|
|
.. code-block:: c++
|
|
|
|
#include <boost/exception/diagnostic_information.hpp>
|
|
#include <iostream>
|
|
|
|
try {
|
|
operationThatMayThrow();
|
|
}
|
|
catch (const std::exception& e) {
|
|
std::cerr << boost::diagnostic_information(e);
|
|
}
|