diff --git a/doc/contributing/source/coding-style.rst b/doc/contributing/source/coding-style.rst index 9a892d363..e9fe210b3 100644 --- a/doc/contributing/source/coding-style.rst +++ b/doc/contributing/source/coding-style.rst @@ -14,135 +14,359 @@ When writing code to be contributed to the |ns3| open source project, we ask that you follow the coding standards, guidelines, and recommendations found below. -Coding style checks -******************* +Clang-format +************ -The |ns3| project maintains Python scripts that check and enforce the adopted -coding style. The following subsections explain them in detail. +The |ns3| project uses `clang-format `_ +to define and enforce the C++ coding style. Clang-format can be easily integrated +with modern IDEs or run manually on the command-line. -check-style.py -============== +Clang-format installation +========================= -A lot of the syntactical rules described can be easily enforced with the -help of the ``utils/check-style.py`` script which relies on a working version -of `uncrustify `_. We recommend to -run this script over your newly introduced C++ files prior to submission -as a Merge Request. -However, we ask that you avoid introducing whitespace changes to any -portions of existing files that do not pertain to your submission (even -though such portions of existing files may not be currently compliant -with the coding style). +Clang-format can be installed using your OS's package manager. Please note that you +should install one of the supported versions of clang-format, which are listed in the +following section. -To run ``check-style.py`` on a new file, the following command is -suggested: +Supported versions of clang-format +================================== -:: +Since each new major version of clang-format can add or modify properties, +newer versions of clang-format might produce different outputs compared to +previous versions. - $ /path/to/utils/check-style.py -i -l 3 -f new-file.cc +The following list contains the set of clang-format versions that are verified +to produce consistent output among themselves. -The ``-i`` flag tells ``check-style.py`` to make modifications in-place. The -``-l 3`` argument asks to apply the highest level of whitespace compliance -changes to the code. +* clang-format-14 +* clang-format-15 +* clang-format-16 -trim_trailing_whitespace.py -=========================== +Integration with IDEs +===================== -The |ns3| coding style states that text files must not have trailing whitespace. -This rule can be easily checked and enforced with the help of the Python script -``utils/trim_trailing_whitespace.py``. +Clang-format automatically integrates with modern IDEs (e.g., VS Code) that read the +``.clang-format`` file and automatically formats the code on save or on typing. -The ``trim_trailing_whitespace.py`` script can be run with the following commands: +Please refer to the documentation of your IDE for more information. +Some examples of IDE integration are provided in +`clang-format documentation `_ -:: +As an example, VS Code can be configured to automatically format code on save, on paste +and on type by enabling the following settings: - # Entire codebase (using paths relative to the ns-3 root) - ./utils/trim-trailing-whitespace.py [--check] . +.. sourcecode:: json - # Entire codebase (using absolute paths) - /path/to/utils/trim-trailing-whitespace.py [--check] /path/to/ns3/root - - # Specific directory - /path/to/utils/trim-trailing-whitespace.py [--check] absolute_or_relative/path/to/directory - - # Individual file - /path/to/utils/trim-trailing-whitespace.py [--check] absolute_or_relative/path/to/file - - -The script has two modes of operation. When no flags are present, the script will -detect and trim trailing whitespace in all text files in the given path. -If the ``--check`` flag is present, the script will only check if there are files -with trailing whitespace, and exit with a non-zero exit code. -This mode is useful for developers editing their code locally and -the GitLab CI/CD pipeline to check if the codebase has trailing whitespace. - -The complete API of the script can be obtained with the following command: - -:: - - $ ./utils/trim-trailing-whitespace.py --help - -Code layout -*********** - -The code layout follows the -`GNU coding standard `_ layout for C and -extends it to C++. Do not use tabs for indentation. Indentation spacing is -2 spaces (the default emacs C++ mode) as outlined below: - -:: - - Foo (void) { - if (test) - { - // do stuff here - } - else - { - // do other stuff here - } - - for (int i = 0; i < 100; i++) - { - // do loop - } - - while (test) - { - // do while - } - - do - { - // do stuff - } while (); + "editor.formatOnSave": true, + "editor.formatOnPaste": true, + "editor.formatOnType": true, } -Each statement should be put on a separate line to increase readability, and -multi-statement blocks following conditional or looping statements are always -delimited by braces (single-statement blocks may be placed on the same line -of an ``if ()`` statement). Each variable declaration is on a separate line. -Variables should be declared at the point in the code where they are needed, -and should be assigned an initial value at the time of declaration. Except -when used in a switch statement, the open and close braces ``{`` and ``}`` -are always on a separate line. Do not use the C++ ``goto`` statement. +Manual usage in the terminal +============================ -The layout of variables declared in a class may either be aligned with -the variable names or unaligned, as long as the file is internally consistent -and no tab characters are included. Examples: +Clang-format can be manually run on the terminal by applying the following commands: -:: +.. sourcecode:: console - int varOne; - double varTwo; // OK (unaligned) - int varOne; - double varTwo; // also OK (aligned) + clang-format -i $FILE + +To check that a file is properly formatted, run the following command on the terminal. +If the code is well formatted, the process will exit with code 0; if is not, it will +exit with code of 1 and indicate the lines that should be formatted. + +.. sourcecode:: console + + clang-format --dry-run --Werror $FILE + +Clang-format Git integration +============================ + +Clang-format can be integrated with Git to reformat existing Git patches, such as +pending merge requests on the GitLab repository. The full documentation is available on +`clang-format Git integration `_ + +In addition to Git patches, +`clang-format-diff `_ +can also be used to reformat existing patches produced with the ``diff`` tool. + +Disable formatting in specific files or lines +============================================= + +To disable formatting in specific lines, surround them with the following +C++ comments [example adopted from +`official clang-format documentation `_]: + +.. sourcecode:: cpp + + // clang-format off + ... + // clang-format on + +To exclude the whole file from being formatted, surround the whole file with the +special comments. + +check-style-clang-format.py +*************************** + +To facilitate checking and fixing source code files according to the |ns3| coding style, +|ns3| maintains the ``check-style-clang-format.py`` Python script (located in ``utils/``). +This script is a wrapper to clang-format and provides useful options to check and fix +source code files. Additionally, it checks and fixes trailing whitespace and tabs in text +files. + +We recommend running this script over your newly introduced C++ files prior to submission +as a Merge Request. + +The script has multiple modes of operation. By default, the script checks if +source code files are well formatted and text files do not have trailing whitespace +nor tabs. The process returns a zero exit code if all files adhere to these rules. +If there are files that do not comply with the rules, the process returns a non-zero +exit code and lists the respective files. This mode is useful for developers editing +their code and for the GitLab CI/CD pipeline to check if the codebase is well formatted. +All checks are enabled by default. Users can disable specific checks using the corresponding +flags: ``--no-formatting``, ``--no-whitespace`` and ``--no-tabs``. + +In addition to checking the files, the script can automatically fix detected issues in-place. +This mode is enabled by adding the ``--fix`` flag. + +The complete API of the ``check-style-clang-format.py`` script can be obtained with the +following command: + +.. sourcecode:: console + + ./utils/check-style-clang-format.py --help + +For quick-reference, the most used commands are listed below: + +.. sourcecode:: console + + # Entire codebase (using paths relative to the ns-3 root) + ./utils/check-style-clang-format.py [--fix] [--no-formatting] [--no-whitespace] [--no-tabs] . + + # Entire codebase (using absolute paths) + /path/to/utils/check-style-clang-format.py [--fix] [--no-formatting] [--no-whitespace] [--no-tabs] /path/to/ns3/root + + # Specific directory + /path/to/utils/check-style-clang-format.py [--fix] [--no-formatting] [--no-whitespace] [--no-tabs] absolute_or_relative/path/to/directory + + # Individual file + /path/to/utils/check-style-clang-format.py [--fix] [--no-formatting] [--no-whitespace] [--no-tabs] absolute_or_relative/path/to/file + +Source code formatting +********************** + +The |ns3| coding style was changed between the ns-3.36 and ns-3.37 release. +Prior to ns-3.37, |ns3| used a base GNU coding style. Since ns-3.37, |ns3| changed the +base coding style to what is known in the industry as Allman-style braces, +with four-space indentation. In clang-format, this is configured by selecting the +``Microsoft`` base style. The following examples illustrate the style. + +Indentation +=========== + +Indent code with 4 spaces. When breaking statements into multiple lines, indent the +following lines with 4 spaces. + +.. sourcecode:: cpp + + void + Func() + { + int x = 1; + } + +Indent constructor's initialization list with 4 spaces. + +.. sourcecode:: cpp + + MyClass::MyClass(int x, int y) + : m_x (x), + m_y (y) + { + } + +Do not use tabs in source code. Always use spaces for indentation and alignment. + +Line endings +============ + +Files use LF (``\n``) line endings. + +Column limit +============ + +Code lines should not extend past 100 characters. This allows reading code in wide-screen +monitors without having to scroll horizontally, while also allowing editing two files +side-by-side. + +Braces style +============ + +Braces should be formatted according to the Allman style. +Braces are always on a new line and aligned with the start of the corresponding block. +The main body is indented with 4 spaces. + +Always surround conditional or loop blocks (e.g., ``if``, ``for``, ``while``) +with braces, and always add a space before the condition's opening parentheses. + +.. sourcecode:: cpp + + void Foo() + { + if (condition) + { + // do stuff here + } + else + { + // do other stuff here + } + + for (int i = 0; i < 100; i++) + { + // do loop + } + + while (condition) + { + // do while + } + + do + { + // do stuff + } while (condition); + } + +Spacing +======= + +To increase readability, functions, classes and namespaces are separated by one +new line. This spacing is optional when declaring variables or functions. +Declare one variable per line. Do not mix multiple statements on the same line. + +Do not add a space between the function name and the opening parentheses. +This rule applies to both function (and method) declarations and invocations. + +.. sourcecode:: cpp + + void Func(const T&); // OK + void Func (const T&); // Not OK + +Trailing whitespace +=================== + +Source code and text files must not have trailing whitespace. + +Code alignment +============== + +To improve code readability, trailing comments should be aligned. + +.. sourcecode:: cpp + + int varOne; // Variable one + double varTwo; // Variable two + +The trailing ``\`` character of macros should be aligned to the far right +(equal to the column limit). This increases the readability of the macro's body, +without forcing unnecessary whitespace diffs on surrounding lines when only one +line is changed. + +.. sourcecode:: cpp + + #define MY_MACRO(msg) \ + do \ + { \ + std::cout << msg << std::endl; \ + } while (false); + + +Class members +============= + +Definition blocks within a class should be organized in descending order of +public exposure, that is: ``static`` > ``public`` > ``protected`` > ``private``. +Separate each block with a new line. + +.. sourcecode:: cpp + + class MyClass + { + public: + static counter = 0; + + MyClass(int x, int y); + + private: + int x; + int y; + }; + +Function arguments bin packing +============================== + +Function arguments should be declared in the same line as the function declaration. +If the arguments list does not fit the maximum column width, declare each one on a +separate line and align them vertically. + +.. sourcecode:: cpp + + void ShortFunction(int x, int y); + + void VeryLongFunctionWithLongArgumentList(int x, + int y, + int z); + + +The constructor initializers are always declared one per line, with a trailing comma: + +.. sourcecode:: cpp + + void + MyClass::MyClass(int x, int y) + : m_x (x), + m_y (y) + { + } + +Function return types +===================== + +In function declarations, return types are declared on the same line. +In function implementations, return types are declared on a separate line. + + +.. sourcecode:: cpp + + // Function declaration + void Func(int x, int y); + + // Function implementation + void + Func(int x, int y) + { + // (...) + } + +Templates +========= + +Template definitions are always declared in a separate line from the main function +declaration: + +.. sourcecode:: cpp + + template + void func(T t); Naming -****** +====== Name encoding -============= +############# Function, method, and type names should follow the `CamelCase `_ convention: words are @@ -175,29 +399,30 @@ with an underscore character separating words. Otherwise, the underscore character should not be used in a variable name. For example, you could declare in your class header ``my-class.h``: -:: +.. sourcecode:: cpp typedef int NewTypeOfInt_t; - const uint8_t PORT_NUMBER = 17; + constexpr uint8_t PORT_NUMBER = 17; class MyClass { - void MyMethod (int aVar); - int m_aVar; - static int m_anotherVar; + void MyMethod(int aVar); + int m_aVar; + static int m_anotherVar; }; and implement in your class file ``my-class.cc``: -:: +.. sourcecode:: cpp int MyClass::m_anotherVar = 10; static int g_aStaticVar = 100; int g_aGlobalVar = 1000; + void - MyClass::MyMethod (int aVar) + MyClass::MyMethod(int aVar) { - m_aVar = aVar; + m_aVar = aVar; } As an exception to the above, the members of structures do not need to be @@ -208,27 +433,27 @@ Finally, do not use do not prefix enums, classes, or delegates with any letter. Choosing names -============== +############## Variable, function, method, and type names should be based on the English language, American spelling. Furthermore, always try to choose descriptive names for them. Types are often english names such as: Packet, Buffer, Mac, or Phy. Functions and methods are often named based on verbs and adjectives: -GetX, DoDispose, ClearArray, etc. +``GetX``, ``DoDispose``, ``ClearArray``, etc. A long descriptive name which requires a lot of typing is always better than a short name which is hard to decipher. Do not use abbreviations in names unless the abbreviation is really unambiguous and obvious to everyone (e.g., -use "size" over "sz"). Do not use short inappropriate names such as foo, +use ``size`` over ``sz``). Do not use short inappropriate names such as foo, bar, or baz. The name of an item should always match its purpose. As such, -names such as "tmp" to identify a temporary variable, or such as "i" to -identify a loop index are ok. +names such as ``tmp`` to identify a temporary variable, or such as ``i`` to +identify a loop index are OK. If you use predicates (that is, functions, variables or methods which return a single boolean value), prefix the name with "is" or "has". File layout and code organization -********************************* +================================= A class named ``MyClass`` should be declared in a header named ``my-class.h`` and implemented in a source file named ``my-class.cc``. The goal of this @@ -245,7 +470,7 @@ to try to track the most appropriate person to review a patch or fix a bug. Please do not add the "All Rights Reserved" phrase after the copyright statement. -:: +.. sourcecode:: cpp /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* @@ -274,12 +499,13 @@ provides a set of Doxygen comments for the public part of your class API. Detailed information on the set of tags available for doxygen documentation is described in the `Doxygen website `_. -:: +.. sourcecode:: cpp #ifndef MY_CLASS_H #define MY_CLASS_H - namespace n3 { + namespace ns3 + { /** * \brief short one-line description of the purpose of your class @@ -290,29 +516,32 @@ is described in the `Doxygen website `_. class MyClass { public: - MyClass (); - /** - * \param firstParam a short description of the purpose of this parameter - * \returns a short description of what is returned from this function. - * - * A detailed description of the purpose of the method. - */ - int DoSomething (int firstParam); + MyClass(); + + /** + * A detailed description of the purpose of the method. + * + * \param firstParam a short description of the purpose of this parameter + * \returns a short description of what is returned from this function. + */ + int DoSomething(int firstParam); + private: - /** - * Private method doxygen is also recommended - */ - void MyPrivateMethod (void); - int m_myPrivateMemberVariable; ///< Brief description of member variable + /** + * Private method doxygen is also recommended + */ + void MyPrivateMethod(); + + int m_myPrivateMemberVariable; ///< Brief description of member variable }; } // namespace ns3 - #endif /* MY_CLASS_H */ + #endif // MY_CLASS_H The ``my-class.cc`` file is structured similarly: -:: +.. sourcecode:: cpp /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* @@ -322,41 +551,114 @@ The ``my-class.cc`` file is structured similarly: * * Author: MyName */ + #include "my-class.h" - namespace ns3 { + namespace ns3 + { - MyClass::MyClass () - {} + MyClass::MyClass() + { + } ... } // namespace ns3 -Language features -***************** +Header file includes +==================== -As of ns-3.36, |ns3| permits the use of C++-17 (or earlier) features -in the implementation files. +Included header files should be organized by source location. The sorting order is +as follows: -If a developer would like to propose to raise this bar to include more -features than this, please email the developers list. We will move this -language support forward as our minimally supported compiler moves forward. +.. sourcecode:: cpp + + // Header class (applicable for *.cc files) + #include "my-class.h" + + // Includes from the same module + #include "header-from-same-module.h" + + // Includes from other modules + #include "ns3/header-from-different-module.h" + + // External headers (e.g., STL libraries) + #include + +Groups should be separated by a new line. Within each group, headers should be +sorted alphabetically. + +For standard headers, use the C++ style of inclusion: + +.. sourcecode:: cpp + + #include // OK + #include // Avoid + +- inside .h files, always use + + .. sourcecode:: cpp + + #include + +- inside .cc files, use + + .. sourcecode:: cpp + + #include "header.h" + + if file is in same directory, otherwise use + + .. sourcecode:: cpp + + #include + +Variables +========= + +Each variable declaration is on a separate line. +Variables should be declared at the point in the code where they are needed, +and should be assigned an initial value at the time of declaration. + +.. sourcecode:: cpp + + // Do not declare multiple variables per line + int x, y; + + // Declare one variable per line and assign an initial value + int x = 0; + int y = 0; Comments -******** +======== The project uses `Doxygen `_ to document the interfaces, and uses comments for improving the clarity of the code -internally. All classes, methods, and members should have Doxygen comments. Doxygen comments -should use the C comment (also known as Javadoc) style. For comments that -are intended to not be exposed publicly in the Doxygen output, use the -``@internal`` and ``@endinternal`` tags. -Please use the ``@see`` tag for cross-referencing. All -parameters and return values should be documented. The |ns3| codebase uses +internally. All classes, methods, and members should have Doxygen comments. +Doxygen comments should use the C-style comment (also known as Javadoc) style. +For comments that are intended to not be exposed publicly in the Doxygen output, +use the ``@internal`` and ``@endinternal`` tags. +Please use the ``@see`` tag for cross-referencing. +All parameters and return values should be documented. The |ns3| codebase uses both the ``@`` or ``\`` characters for tag identification; please make sure that usage is consistent within a file. +.. sourcecode:: cpp + + /** + * MyClass description. + */ + class MyClass + { + /** + * Constructor. + * + * \param n Number of elements. + */ + MyClass(int n); + }; + + As for comments within the code, comments should be used to describe intention or algorithmic overview where is it not immediately obvious from reading the code alone. There are no minimum comment requirements and small routines @@ -368,9 +670,10 @@ emacs sentence commands work. Sometimes ``NS_LOG_DEBUG`` statements can be also used in place of comments. Short one-line comments and long comments can use the C++ comment style; -that is, ``//``, but longer comments may use C-style comments: +that is, ``//``, but longer comments may use C-style comments. +Use one space after ``//`` or ``/*``. -:: +.. sourcecode:: cpp /* * A longer comment, @@ -383,31 +686,166 @@ obvious from the context. The short comment should be on the same line as the variable declaration, unless it is too long, in which case it should be on the preceding lines. +.. sourcecode:: cpp + + int nNodes = 3; // Number of nodes + + /// Node container with the Wi-Fi stations + NodeContainer wifiStations(3); + Casts -***** +===== Where casts are necessary, use the Google C++ guidance: "Use C++-style casts -like ``static_cast(double_value)``, or brace initialization for +like ``static_cast (double_value)``, or brace initialization for conversion of arithmetic types like ``int64 y = int64{1} << 42``." +Do not use C-style casts, since they can be unsafe. Try to avoid (and remove current instances of) casting of ``uint8_t`` type to larger integers in our logging output by overriding these types within the logging system itself. Also, the unary ``+`` operator can be used to print the numeric value of any variable, such as: -:: +.. sourcecode:: cpp uint8_t flags = 5; std::cout << "Flags numeric value: " << +flags << std::endl; Avoid unnecessary casts if minor changes to variable declarations can solve -the issue. +the issue. In the following example, ``x`` can be declared as ``float`` instead of +``int`` to avoid the cast: + +.. sourcecode:: cpp + + // Do not declare x as int, to avoid casting it to float + int x = 3; + return 1 / static_cast(x); + + // Prefer to declare x as float + float x = 3.0; + return 1 / x; + +Namespaces +========== + +Code should always be included in a given namespace, namely ``ns3``. +In order to avoid exposing internal symbols, consider placing the code in an +anonymous namespace, which can only be accessed by functions in the same file. + +Code within namespaces should not be indented. To more easily identify the end +of a namespace, add a trailing comment to its closing brace. + +.. sourcecode:: cpp + + namespace ns3 + { + + // (...) + + } // namespace ns3 + +Namespace names should follow the snake_case convention. + +Unused variables +================ + +Compilers will typically issue warnings on unused entities (e.g., variables, +function parameters). Use the ``[[maybe_unused]]`` attribute to suppress +such warnings when the entity may be unused depending on how the code +is compiled (e.g., if the entity is only used in a logging statement or +an assert statement). Example (parameter ``p`` is only used for logging): + +.. sourcecode:: cpp + + void + TcpSocketBase::CompleteFork(Ptr p [[maybe_unused]], + const TcpHeader& h, + const Address& fromAddress, + const Address& toAddress) + { + NS_LOG_FUNCTION(this << p << h << fromAddress << toAddress); + ... + } + +In function or method parameters, if the parameter is definitely unused, +it should be left unnamed. Example (second parameter is not used): + +.. sourcecode:: cpp + + void + UanMacAloha::RxPacketGood(Ptr pkt, double, UanTxMode txMode) + { + UanHeaderCommon header; + pkt->RemoveHeader(header); + ... + } + +In this case, the parameter is also not referenced by Doxygen; e.g.,: + +.. sourcecode:: cpp + + /** + * Receive packet from lower layer (passed to PHY as callback). + * + * \param pkt Packet being received. + * \param txMode Mode of received packet. + */ + void RxPacketGood(Ptr pkt, double, UanTxMode txMode); + +The omission is preferred to commenting out unused parameters, such as: + +.. sourcecode:: cpp + + void + UanMacAloha::RxPacketGood(Ptr pkt, double /*sinr*/, UanTxMode txMode) + { + UanHeaderCommon header; + pkt->RemoveHeader(header); + ... + } + +Smart pointer boolean comparisons +================================= + +As explained in this `issue `_, +the |ns3| smart pointer class ``Ptr`` should be used in boolean comparisons as follows: + +.. sourcecode:: cpp + + for Ptr<> p, do not use: use instead: + ======================== ================================= + if (p != 0) {...} if (p) {...} + if (p != NULL) {...} + if (p != nullptr {...} + + if (p == 0) {...} if (!p) {...} + if (p == NULL) {...} + if (p == nullptr {...} + + NS_ASSERT... (p != 0, ...) NS_ASSERT... (p, ...) + NS_ABORT... (p != 0, ...) NS_ABORT... (p, ...) + + NS_ASSERT... (p == 0, ...) NS_ASSERT... (!p, ...) + NS_ABORT... (p == 0, ...) NS_ABORT... (!p, ...) + + NS_TEST... (p, 0, ...) NS_TEST... (p, nullptr, ...) + +C++ standard +============ + +As of ns-3.36, |ns3| permits the use of C++-17 (or earlier) features +in the implementation files. + +If a developer would like to propose to raise this bar to include more +features than this, please email the developers list. We will move this +language support forward as our minimally supported compiler moves forward. Miscellaneous items -******************* +=================== - The following emacs mode line should be the first line in a file: - :: + + .. sourcecode:: cpp /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ @@ -416,137 +854,54 @@ Miscellaneous items ``using namespace ns3;``. In examples. ``NS_OBJECT_ENSURE_REGISTERED()`` should also be placed within namespace ns3. +- Pointers and references are left-aligned: + + .. sourcecode:: cpp + + int x = 1; + int* ptr = &x; + int& ref = x; + - Const reference syntax: - :: - void MySub (const T&); // Method 1 (prefer this syntax) - void MySub (T const&); // Method 2 (avoid this syntax) + .. sourcecode:: cpp -- Use a space between the function name and the parentheses, e.g.: - :: - - void MySub(const T&); // avoid this - void MySub (const T&); // use this instead - This spacing rule applies both to function declarations and invocations. + void MySub(const T& t); // OK + void MySub(T const& t); // Not OK - Do not include inline implementations in header files; put all implementation in a .cc file (unless implementation in the header file brings demonstrable and significant performance improvement). -- Do not use ``nil`` or ``NULL`` constants; use ``0`` (improves portability) +- Do not use ``nil``, ``NULL`` or ``0`` constants; use ``nullptr`` (improves portability) - Consider whether you want the default constructor, copy constructor, or assignment - operator in your class, and if not, explicitly mark them as deleted: - :: + operator in your class. If not, explicitly mark them as deleted and make the + declaration public: + + .. sourcecode:: cpp public: // Explain why these are not supported - ClassName () = delete; - ClassName (const ClassName&) = delete; - ClassName& operator= (const ClassName&) = delete; + ClassName() = delete; + ClassName(const ClassName&) = delete; + ClassName& operator=(const ClassName&) = delete; - Avoid returning a reference to an internal or local member of an object: - :: - a_type& foo (void); // should be avoided, return a pointer or an object. - const a_type& foo (void); // same as above + .. sourcecode:: cpp + + a_type& foo(); // should be avoided, return a pointer or an object. + const a_type& foo(); // same as above + This guidance does not apply to the use of references to implement operators. - Expose class members through access functions, rather than direct access - to a public object. The access functions are typically named Get" and - "Set". For example, a member m_delayTime might have accessor functions - ``GetDelayTime ()`` and ``SetDelayTime ()``. - -- For standard headers, use the C++ style of inclusion, such as - :: - - #include - instead of - :: - - #include + to a public object. The access functions are typically named ``Get`` and + ``Set``. For example, a member ``m_delayTime`` might have accessor functions + ``GetDelayTime()`` and ``SetDelayTime()``. - Do not bring the C++ standard library namespace into |ns3| source files by - using the "using" directive; i.e. avoid ``using namespace std;``. - -- When including |ns3| headers in other |ns3| files, use `<>` when you expect - the header to be found in build/ (or to be installed) and use `""` when - you know the header is in the same directory as the implementation. - - - inside .h files, always use - :: - - #include - - - inside .cc files, use - :: - - #include "header.h" - if file is in same directory, otherwise use - :: - - #include - -- Compilers will typically issue warnings on unused entities (e.g., variables, - function parameters). Use the ``[[maybe_unused]]`` attribute to suppress - such warnings when the entity may be unused depending on how the code - is compiled (e.g., if the entity is only used in a logging statement or - an assert statement). Example (parameter 'p' is only used for logging): - :: - void - TcpSocketBase::CompleteFork (Ptr p [[maybe_unused]], const TcpHeader& h, - const Address& fromAddress, const Address& toAddress) - { - NS_LOG_FUNCTION (this << p << h << fromAddress << toAddress); - ... - - In function or method parameters, if the parameter is definitely unused, - it should be left unnamed. Example (second parameter is not used): - :: - void - UanMacAloha::RxPacketGood (Ptr pkt, double, UanTxMode txMode) - { - UanHeaderCommon header; - pkt->RemoveHeader (header); - ... - - In this case, the parameter is also not referenced by Doxygen; e.g.: - :: - /* - * Receive packet from lower layer (passed to PHY as callback). - * - * \param pkt Packet being received. - * \param txMode Mode of received packet. - */ - void RxPacketGood (Ptr pkt, double, UanTxMode txMode); - - The omission is preferred to commenting out unused parameters such as: - :: - void - UanMacAloha::RxPacketGood (Ptr pkt, double /*sinr*/, UanTxMode txMode) - { - UanHeaderCommon header; - pkt->RemoveHeader (header); - ... - -- As explained in this `issue `_, - the ns-3 smart pointer class ``Ptr`` should be used in boolean comparisons as follows: - :: - for Ptr<> p, do not use: use instead: - ======================== ================================= - if (p != 0) {...} if (p) {...} - if (p != NULL) {...} - if (p != nullptr {...} - - if (p == 0) {...} if (!p) {...} - if (p == NULL) {...} - if (p == nullptr {...} - - NS_ASSERT... (p != 0, ...) NS_ASSERT... (p, ...) - NS_ABORT... (p != 0, ...) NS_ABORT... (p, ...) - - NS_ASSERT... (p == 0, ...) NS_ASSERT... (!p, ...) - NS_ABORT... (p == 0, ...) NS_ABORT... (!p, ...) - - NS_TEST... (p, 0, ...) NS_TEST... (p, nullptr, ...) + using the ``using`` directive; i.e., avoid ``using namespace std;``. +- Do not use the C++ ``goto`` statement. diff --git a/doc/contributing/source/general.rst b/doc/contributing/source/general.rst index d21c0996a..7edf1c391 100644 --- a/doc/contributing/source/general.rst +++ b/doc/contributing/source/general.rst @@ -191,15 +191,14 @@ Coding style We ask that all contributors make their code conform to the coding standard which is outlined in :ref:`Coding style`. -The project maintains a Python program called ``check-style.py`` found in -the ``utils/`` directory. This is a wrapper around the ``uncrustify`` -utility with configuration set to the conventions used by |ns3|, and -can be used to quickly format new source code files proposed for the -mainline. +The project maintains a Python program called ``check-style-clang-format.py`` found in +the ``utils/`` directory. This is a wrapper around the ``clang-format`` +utility and can be used to quickly format new source code files proposed for the +mainline. The |ns3| coding style conventions are defined in the corresponding +``.clang-format`` file. -Additionally, the project also maintains a Python program called -``trim_trailing_whitespace.py``, found in the ``utils/`` directory. -This program checks and trims trailing whitespace in text files, in order to +In addition to formatting source code files with ``clang-format``, the Python program +also checks trailing whitespace in text files and converts tabs to spaces, in order to comply with the |ns3| coding style. Creating a patch