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 namespace is **not** indented. Avoid the following:

    .. code-block:: c++

        // NOT
        //
        // 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 {
        namespace analyzer {

        ...

        } // namespace analyzer
        } // namespace model

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