Skip to content
Snippets Groups Projects
codingStyleGuide.org 15.91 KiB

OpenFOAM C++ style guide

#

OpenFOAM C++ style guide

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 brace brackets. 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 brace brackets.
  • A fall-through case should be commented as such.
  • stream output
    • << is always four characters after the start of the stream, so that the << symbols align, i.e.
      Info<< ...
      os  << ...
              

      so

      WarningIn("className::functionName()")
          << "Warning message"
              

      not

      WarningIn("className::functionName()")
      << "Warning message"
              
  • no 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 are centred
/*---------------------------------------------------------------------------*\
                        Class exampleClass Declaration
\*---------------------------------------------------------------------------*/

not

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

The .H 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
    • If 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 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, 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 and scalar 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.

The 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