| 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); |
| } |