The coding style for Itlab CPP Library

Names

class names
camel-case, starting with capital letter; example: BayerImage
methods
camel-case, starting with small letter; example: getUCharP()
attributes (member variables)
camel-case, starting with small letter, ending with underscore; srcImg_
local variables
camel-case, starting with small letter.
templates
template classes as normal classes, template functions/methods as normal functions/methods.
macros
all-caps; example: #define FW_BUS_ID(i) (0x1002380+(i)*0x10)
simple types in typedefs
camel-case, starting with small letter, ending with _t; example: typedef int handle_t
structs
camel-case, starting with small letter; example: struct fPoint3

Structs may not contain member functions (methods), and are usually not typedef'd.

Do not use Hungarian notation (for instance pszName meaning pointer to zero-terminated string). Instead, add documentation to where your variables are declared.

Use the proper variable names in function declarations in headers, it helps understanding the interface by reading the header file. And the names should be descriptive, not a single letter nor misleading.

implementation files
class name with .cc extension.
header files
class name with .hh extension.
template files
class name with .hh extension.

Indentation and Lines

Use only tabs for block indenting, not spaces. Tab width is 8 characters for computing line lengths. Maximum line length is 79 characters. This may feel too deep indentation, but when you are doing more than 5 levels of indenting, think about if it should be broken into functions. An exception are switch..case sections, which can be indented as following:

Image & createImage(enum imtype t)
{
	switch(t)
	{
	case TYPE_RGB:
		return RGBImage();
	case TYPE_GRAY:
		return GrayImage();
	default:
		throw std::invalid_argument("Unknown image type.");
	}
}

Alignment, which is not block indenting, must be done with spaces. Tabs can be used only as the first characters of a line (Reasoning: http://mcf.ath.cx/Docs/libmcf/CodeStyle.html ).

Long function declarations and long function calls are indented by alignment (if at all possible, sometimes line length may prevent this):

ret = object.dummyFunction(img->height(), img->width(),
                           img->depth(), img->getUCharP(),
                           TYPE_RGB);

Currently, it seems that “bsd” indentation style in Emacs gives the desired indentation. Set that with C-c . bsd <ret>. After that you can indent the current function using C-c C-q or a marked region by M-x indent-region. You can also make the style setting automatically per file by inserting the following as the first line of the file:

/* -*- c-file-style: "bsd" -*- */

Write only one statement on a line.

Blocks

The opening and closing curly braces {} must be at the same indentation level. Examples:

void dummy(int cnt)
{
	int i = 0;
	
	do
	{
		++i;
	} while(i<cnt);
	
	if(cnt > 10)
	{
		std::cout << "That was long." << std::endl;
		i = 10;
	} else
	{
		std::cout << "Short!" << std::endl;
	}
}

Documentation

Use Doxygen documentary comments. Short documentation can be in header files as /// and ///< comments, longer documentations for methods in implementation files, for instance:

/** @brief Query information about a video channel.
  *
  * You have to allocate a struct video_channel yourself for calling
  * this function.
  * @pre The device must be opened.
  * @param[[out]] vc Structure for returning channel information.
  * @param[[in]] chan The channel number, starting from 0.
  * @throw GenError The channel number was out of range.
  * @throw StdError Querying channel properties failed.
  * @sa print_channel_info(), channel(), channels(), set_channel()
  */
void Videodev::channel_info(struct video_channel * const vc,
                            const int chan) const throw (GenError)
{

And an example of the shorter comments:

        /// List of video palettes in V4L, see the list in %Videodev.cc source.
        static struct tag_palettes
        {
                const int palette; ///< palette id as in V4L
                const char *str;   ///< palette name (e.g. in configs)
                const char *desc;  ///< short description, for the user
        } palettes[[]];

Long class documentation must be put in the header files right before class declaration. Having method documentation in implementation files makes the class declaration shorter and easier to read. Of course, these rules may need to be bent for template classes and implementations in header files.

Coding guidelines

As said, these are general guidelines that should be adhered to whenever possible.

  • Never put a using statement in a header file. Users do not expect that including a header might mess with the default namespace.
  • When you #include a file in a public library header, always use <> notation.
  • In other cases, when you #include a file, put the name in double quotes (“”) only, if the header is in the current directory. All other times use angle brackets (<>)
  • In library headers, do not #include another header file if a simple forward declaration suffices.
  • Prefer to use std::string instead of char arrays and char pointers.
  • Prefer the standard exception classes from stdexcept. If you need a stack trace to be recorded into the exception, you may consider GenError and StdError from Utils.
  • Do use exceptions for exceptional errors, but never as a part of normal expected program execution flow.
  • Do use the const keyword:
    • method return types (pointers and references)
    • method parameters
    • methods (i.e. const method of a class)
    • varibles and attributes (e.g. const ObjectClass * const fooptr)
  • Never call exit() on error, throw an exception instead.
  • Try to keep interfaces simple and minimal.

Examples

GLPixelBufferObject

itlab/itlabcpp/base/src/GLGraphics/GLPixelBUfferObject.hh is an example of how to use the coding style for writing a template class. It demonstrates the license, using C-headers, documenting with Doxygen, and other coding style issues, which may not have been defined here, but are a good practice. Notable things are documenting the use quirks properly (in writeToTexture()) and denying default constructor, copy constructor and assignment operator when they are not expected.

Hints

  • Using snprintf on a std::string is impossible (is it?), try to use std::ostringstream from IOstream library instead.