Skip to content
Snippets Groups Projects
codingStyleGuide.org 16.77 KiB

OpenFOAM C++ Style Guide

#

Code

General

  • 80 character lines max
  • The normal indentation is 4 spaces per logical level.
  • Use spaces for indentation, not tab characters.
  • Avoid trailing whitespace.
  • The body of control statements (eg, if, else, while, etc.). is always delineated with braces. A possible exception can be made in conjunction with break or continue as part of a control structure.
  • The body of case statements is usually delineated with braces.
  • Stream output
    • << is always four characters after the start of the stream, so that the << symbols align, i.e.
      Info<< ...
      os  << ...
              

      so

      WarningInFunction
          << "Warning message"
              

      not

      WarningInFunction
      << "Warning message"
              
  • Remove unnecessary class section headers, i.e. remove
// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //

    // Check

    // Edit

    // Write

if they contain nothing, even if planned for ‘future use’

  • Class titles should be centred
/*---------------------------------------------------------------------------*\
                        Class exampleClass Declaration
\*---------------------------------------------------------------------------*/

not

/*---------------------------------------------------------------------------*\
                Class exampleClass Declaration
\*---------------------------------------------------------------------------*/

The .H Header Files

  • Header file spacing
    • Leave two empty lines between sections (as per functions in the .C file etc.)
  • Use //- Comment comments in header file to add descriptions to class data and functions do be included in the Doxygen documentation:
    • Text on the line starting with //- becomes the Doxygen brief description;
    • Text on subsequent lines becomes the Doxygen detailed description e.g.
      //- A function which returns a thing
      //  This is a detailed description of the function
      //  which processes stuff and returns other stuff
      //  depending on things.
      thing function(stuff1, stuff2);
              
    • List entries start with - or -# for numbered lists but cannot start on the line immediately below the brief description so
      //- Compare triFaces
      //  Returns:
      //  -  0: different
      //  - +1: identical
      //  - -1: same face, but different orientation
      static inline int compare(const triFace&, const triFace&);
              

      or

      //- Compare triFaces returning 0, +1 or -1
      //
      //  -  0: different
      //  - +1: identical
      //  - -1: same face, but different orientation
      static inline int compare(const triFace&, const triFace&);
              

      not

      //- Compare triFaces returning 0, +1 or -1
      //  -  0: different
      //  - +1: identical
      //  - -1: same face, but different orientation
      static inline int compare(const triFace&, const triFace&);
              
    • List can be nested for example
      //- Search for \em name
      //  in the following hierarchy:
      //  -# personal settings:
      //    - ~/.OpenFOAM/\<VERSION\>/
      //      <em>for version-specific files</em>
      //    - ~/.OpenFOAM/
      //      <em>for version-independent files</em>
      //  -# site-wide settings:
      //    - $WM_PROJECT_INST_DIR/site/\<VERSION\>
      //      <em>for version-specific files</em>
      //    - $WM_PROJECT_INST_DIR/site/
      //      <em>for version-independent files</em>
      //  -# shipped settings:
      //    - $WM_PROJECT_DIR/etc/
      //
      //  \return the full path name or fileName() if the name cannot be found
      //  Optionally abort if the file cannot be found
      fileName findEtcFile(const fileName&, bool mandatory=false);
              
    • For more details see the Doxygen documentation.
  • Destructor
    • When adding a comment to the destructor use //- and code as a normal function:
      //- Destructor
      ~className();
              
  • Inline functions
    • Use inline functions where appropriate in a separate classNameI.H file. Avoid cluttering the header file with function bodies.

The .C Sourcs Files

  • Do not open/close namespaces in a .C file
    • Fully scope the function name, i.e.
      Foam::returnType Foam::className::functionName()
              

      not

      namespace Foam
      {
          ...
          returnType className::functionName()
          ...
      }
              

      Exception When there are multiple levels of namespace, they may be used in the .C file to avoid excessive clutter, i.e.

      namespace Foam
      {
      namespace compressible
      {
      namespace RASModels
      {
          ...
      } // End namespace RASModels
      } // End namespace compressible
      } // End namespace Foam
              
  • Use two empty lines between functions

Coding Practice

  • Passing data as arguments or return values:
    • Pass bool, label, scalar and other primitive types as copy, anything larger by reference.
  • const
    • Use everywhere it is applicable.
  • Variable initialisation using
    const className& variableName = otherClass.data();
        

    not

    const className& variableName(otherClass.data());
        
  • Virtual functions
    • If a class is virtual, make all derived classes virtual.

Conditional Statements

if (condition)
{
    code;
}

OR

if
(
   long condition
)
{
    code;
}

not (no space between if and ( used)

if(condition)
{
    code;
}

for and while Loops

for (i = 0; i < maxI; i++)
{
    code;
}

OR

for
(
    i = 0;
    i < maxI;
    i++
)
{
    code;
}

not this (no space between for and ( used)

for(i = 0; i < maxI; i++)
{
    code;
}

Note that when indexing through iterators, it is often slightly more efficient to use the pre-increment form. Eg, ++iter instead of iter++

forAll, forAllIter, forAllConstIter, etc. loops

Like for loops, but

forAll(

not

forAll (

Using the forAllIter and forAllConstIter macros is generally advantageous - less typing, easier to find later. However, since they are macros, they will fail if the iterated object contains any commas e.g. following will FAIL!:

forAllIter(HashTable<labelPair, edge, Hash<edge>>, foo, iter)

These convenience macros are also generally avoided in other container classes and OpenFOAM primitive classes.

Splitting Over Multiple Lines

Splitting return type and function name
  • Split initially after the function return type and left align
  • Do not put const onto its own line - use a split to keep it with the function name and arguments.
    const Foam::longReturnTypeName&
    Foam::longClassName::longFunctionName const
        

    not

    const Foam::longReturnTypeName&
        Foam::longClassName::longFunctionName const
        

    nor

    const Foam::longReturnTypeName& Foam::longClassName::longFunctionName
    const
        

    nor

    const Foam::longReturnTypeName& Foam::longClassName::
    longFunctionName const
        
  • If it needs to be split again, split at the function name (leaving behind the preceding scoping =::=s), and again, left align, i.e.
    const Foam::longReturnTypeName&
    Foam::veryveryveryverylongClassName::
    veryveryveryverylongFunctionName const
        
Splitting long lines at an “=”

Indent after split

variableName =
    longClassName.longFunctionName(longArgument);

OR (where necessary)

variableName =
    longClassName.longFunctionName
    (
        longArgument1,
        longArgument2
    );

not

variableName =
longClassName.longFunctionName(longArgument);

nor

variableName = longClassName.longFunctionName
(
    longArgument1,
    longArgument2
);

Maths and Logic

  • Operator spacing
    a + b, a - b
    a*b, a/b
    a & b, a ^ b
    a = b, a != b
    a < b, a > b, a >= b, a <= b
    a || b, a && b
        
  • Splitting formulae over several lines

    Split and indent as per “splitting long lines at an =” with the operator on the lower line. Align operator so that first variable, function or bracket on the next line is 4 spaces indented i.e.

    variableName =
        a*(a + b)
       *exp(c/d)
       *(k + t);
        

    This is sometimes more legible when surrounded by extra parentheses:

    variableName =
    (
        a*(a + b)
       *exp(c/d)
       *(k + t)
    );
        
  • Splitting logical tests over several lines

    outdent the operator so that the next variable to test is aligned with the four space indentation, i.e.

    if
    (
        a == true
     && b == c
    )
        

Documentation

General

  • For readability in the comment blocks, certain tags are used that are translated by pre-filtering the file before sending it to Doxygen.
  • The tags start in column 1, the contents follow on the next lines and indented by 4 spaces. The filter removes the leading 4 spaces from the following lines until the next tag that starts in column 1.
  • The ‘Class’ and ‘Description’ tags are the most important ones.
  • The first paragraph following the ‘Description’ will be used for the brief description, the remaining paragraphs become the detailed description. For example,
    Class
        Foam::myClass
    
    Description
        A class for specifying the documentation style.
    
        The class is implemented as a set of recommendations that may
        sometimes be useful.
        
  • The class name must be qualified by its namespace, otherwise Doxygen will think you are documenting some other class.
  • If you don’t have anything to say about the class (at the moment), use the namespace-qualified class name for the description. This aids with finding these under-documented classes later.
    Class
        Foam::myUnderDocumentedClass
    
    Description
        Foam::myUnderDocumentedClass
        
  • Use ‘Class’ and ‘Namespace’ tags in the header files. The Description block then applies to documenting the class.
  • Use ‘InClass’ and ‘InNamespace’ in the source files. The Description block then applies to documenting the file itself.
    InClass
        Foam::myClass
    
    Description
        Implements the read and writing of files.
        

Doxygen Special Commands

Doxygen has a large number of special commands with a \ prefix.

Since the filtering removes the leading spaces within the blocks, the Doxygen commmands can be inserted within the block without problems.

InClass
    Foam::myClass

Description
    Implements the read and writing of files.

    An example input file:
    \verbatim
        patchName
        {
            type        myPatchType;
            refValue    100;
            value       uniform 1;
        }
    \endverbatim

    Within the implementation, a loop over all patches is done:
    \code
        forAll(patches, patchi)
        {
            ...  // some operation
        }
    \endcode

HTML Special Commands