Skip to content

coding style guideline

Fabien Spindler edited this page Jun 26, 2024 · 18 revisions

ViSP coding style guideline

Files

  • Each class has its own header and implementation file
  • A template class has only a header file
  • The file name should match the class name
  • C++ interface headers have .h extension
  • Implementation files have .cpp extension
  • As an example, if the class is named vpMyNewClass, the header file name should be vpMyNewClass.h and the implementation file vpMyNewClass.cpp

File structure

Every source file starts with GPL-v2 license. Use existing code to get the template.

Other rules for both header and implementation files include:

  • Code lines should not be very long. Normally, they should be limited to 120 characters.

  • No tabulation should be used. Set your editor to use spaces instead. We recommend to use the provided Visual Code settings.

  • Only English text is allowed. Do not put comments or string literals in other languages.

  • Indentation is 2 spaces.

  • Each file (.h or .cpp) should end with an empty line to avoid a compiler warning

  • Each header should include visp3/core/vpConfig.h before other ViSP headers.

  • Header files must use guarding macros, protecting the files from repeated inclusion:

      #ifndef VP_MY_NEW_CLASS_H
      #define VP_MY_NEW_CLASS_H
    
      #include <visp3/core/vpConfig.h>
      ...
      #endif
    
  • C++ macro should be upper-case like in the previous example

Naming conventions

  • Class names start with a vp prefix, then each name starts with an uppercase letter. Underscores are not allowed; ie vpMyNewClass
  • Macros and enumeration constants are written with all capital letters. Words are separated by underscore. Macro should match the regular expression: ^[A-Z][A-Z0-9_]*$
  • All external functions and classes must use VISP_EXPORT, otherwise there will be linking errors on Windows.
  • Member or static functions start with a lowercase, then next words with an uppercase; ie vpMyNewClass::myNewMethod().

Class implementation conventions

  • A class should have a default constructor, a virtual destructor and a copy operator. The header file vpMyNewClass.h should contain at least the following:

      class VISP_EXPORT vpMyNewClass
      {
      public:
        vpMyNewClass();                                       // Default constructor
        virtual ~vpMyNewClass();                              // Virtual destructor
        const vpMyNewClass& operator=(const vpMyNewClass &v); // Copy operator
        ...
      };
    

Documentation

The documentation is written in doxygen style. Use the existing documentation as example. Normally, each function/method description includes:

  • a short description
  • all the parameters explained; e.g. specify, which image types are accepted, what would be the recommended values for the parameter and how they affect the algorithm etc.
  • the full description with short use samples, references to papers, formulas, etc

In order to avoid warnings when building with Xcode for iOS, the following style should be adopted for

  • Parameter description: use doxygen \param special command to describe only one parameter:

      /*!
        \param x : Coordinates of a point along x-axis.
        \param y : Coordinates of a point along y-axis.
       */
      void myClass::myMethod(double x, double y)
    

    The following is not allowed:

      /*!
        \param x,y : Coordinates of a point.
       */
      void myClass::myMethod(double x, double y)
    
  • Putting documentation after members: use doxygen ///< special character instead of //!<

      int var; ///< Value used to... 
    

Code layout

  • Currently used in ViSP and recommended formatting style looks as follows:

    if (B <= A) {
      throw (vpException(vpException::badValue, "Bad gray levels with %d <= %A", B, A)) ;
    }
    unsigned char v;
    
    double factor = static_cast<double>(B_star - A_star)/static_cast<double>(B - A);
    const unsigned int width = I.getWidth(); 
    const unsigned int height = I.getHeight();
    for (unsigned int i=0 ; i < height; ++i) {
      for (unsigned int j=0 ; j < width; ++j) {
        v = I[i][j];
    
        if (v <= A) {
          I[i][j] = A_star;
        }
        else if (v >= B) {
          I[i][j] = B_star;
        }
        else {
          I[i][j] = static_cast<unsigned char>(A_star + (factor * (v - A)));
        }
      }
    }
    
  • Old style cast is not allowed

    double pi = 3.1415;
    int val = (int)pi; // Not allowed
    

    Use rather a more verbose C++ cast style

    double pi = 3.1415;
    int val = static_cast<int>(pi);
    
  • Identifier should be shorter or equal to 31 characters The following examples are not allowed:

    typedef enum { car, bus, truck } vpLargeTransportationVehiculeTypename; // Not allowed, type name has 37 characters
    void computeImageProcessingOnColorImage(const vpImage<vpRGBa> &I); // Not allowed, function name has 34 characters
    

    Use rather something like:

    typedef enum { car, bus, truck } vpLargeVehiculeType;
    void computeImageProcessing(const vpImage<vpRGBa> &I); 
    
  • Use only one statement per line

    switch(val) {
      case 1:
        val += 1; break; // Not allowed
    }
    

    Use rather:

    switch(val) {
      case 1:
        val += 1; 
        break; 
    }
    
  • A function has at least 7 parameters