C++ Coding Conventions


Naming conventions

For naming conventions we follow the Taligent rules. Up to now they have written the largest body of C++ and the rules seem well thought out. No need to invent something else. The only addition/change we made is to append an _t to typedefs and simple structs, e.g.:
    typedef int Int_t;
    struct Simple_t { ..... }; 
Addherence to the rules is mandatory. Any deviation will cause confusion and chaos. After a while one really gets used to the fact that all class fields start with an f followed by a capitalized word, fEnergy, or that TCollection is a class. If the convention is sporadically violated debugging becomes a nightmare. The usage of a standard begin letter or token for the different types also makes it easy to parse and search the code using simple tools.

Class definition conventions

Also here the Taligent guide is quite reasonable. Of course, no class data member should ever be public (OO remember). Make the data fields always private. Or protected, if you want to grant an inherited class direct access. Concerning inlines. Add trivial get or setters directly in the class definition (improves reading time since one does not have to look for it somewhere else). Add more complex inlines (longer than one line) at the bottom of the .h file. Creating separate .icc files increase the build time, the complexity of the Makefile and, more importantly, increases the number of files one possibly has to scan to find a piece of code (remember code is write once, read often).

Avoid raw C types

Avoid the use of raw C types like int, long, float, double when using data that might be written to disk. For example, the sizes of int and long are machine dependent. On an old PC an int is 16 bits and a long is 32 bits. On 32 bit workstations int's are 32 bits, but on 64 bit processors an int can be either 32 or 64 bits, depending on the processor. For portability reasons and consistent numerical results use typedefs for the basic raw C types. E.g.:
   #ifdef B64
   typedef int            Long_t;      //large integer
   typedef unsigned int   ULong_t;     //large integer
   #else
   typedef long           Long_t;      //large integer
   typedef unsigned long  ULong_t;     //large integer
   #endif
Click here to view all ROOT defined types.

New features like, templates, exception handling, RTTI and namespaces

Of these four new language features templates are the most evolved. However, good template support is still very limited and very compiler dependent. Most Cfront based compilers take extremely long instantiating templates when linking the program. One or two template classes are no problem, but more causes an exponential degradation in link performance. This is especially painful in the frequent edit-compile-link cycles during code development. Some PC compilers have better template support. In general it is expected to take a few more years before templates are performantly supported over the full range of platforms. In the meantime, design your classes in such a way that later they can easily be replaced by templatized versions.

Exception handling is only rudimentary supported by most compilers. Here, however, no link time penalty but a run time penalty is incured (the run time needs to keep track of the resources to be freed when an exception is thrown). Also here PC compilers are leading the way. For the time being wrap setjmp and longjmp calls in TRY, THROW and CATCH macros. This will not provide the full exception handling functionality but at least it will get you going and enables your program to handle the most basic problems like floating point exceptions, bus errors, segmentation violations, etc.

RTTI, run time type identification, is the latest addition to the proposed C++ standard. Only a few PC compilers support it. Once RTTI is allround available it will allow a simplification of many I/O schemes (this is also one of the reasons why the current ODMG standardization effort is way too premature (who would have liked to standardize C++ in 1985?)).

Namespaces are not even supported by PC compilers. As long as they cannot be used extend the T for class names to something like TNa..., e.g. TNaTrack, for NA49 code.

Using comments to document the code

Using the information stored in the dictionary and the source files ROOT can automatically generate a hyperized version of the header and source files. By placing comments in a few strategic places a complete reference manual, including graphics, can be generated using the THtml class.

There are three different kind of comments used by THtml.

Data member description comments
Comments behind a data member definition in the header file, e.g.:
   Float_t     fEnergy;     // the particle energy
The comment "the particle energy" will be put in the dictionary and used whenever fEnergy needs to be described (e.g. on-line help). Have a look at a raw header file and compare it to the hyperized version.

Class description comments
A comment block at the top of the source file describing the class. This block has to be preceeded by a line containing a C++ comment token followed a delimiter string. All comment lines after this starting line are part of the class description, e.g.:
//________________________________________________________________________
//
// TPrimitive
//
// This class is the abstract base class of geometric primitives.
// Use this class by inheriting from it and overriding the
// members, Draw() and List().
//
For an example of a class description comment block see this source file and compare it to the hyperized version.

Member function description comments
The first comment lines after the opening bracket ({) of a member function are considered a description of the function. For example:
TList::Insert()
{
   // Insert node into linked list.
   // To insert node at end of list use Add().
   ...
   ...
}
Here the two comment lines after the { are used to describe the working and usage of the member function. For a real life example see this source file and compare it to the hyperized version.

HTML directly in the source

In the class and member function description comments one can also insert "raw" HTML. This gives the possibility to have nicely formatted text or, more importantly, to be able to include graphics into the source showing, for example, a data structure, an algorithm an inheritance tree, etc. For example:
TList::Insert()
{
   // Insert node into linked list.
   // To insert node at end of list use Add().
   //Begin_Html
   /*
   <img src="gif/list.gif">
   */
   //End_Html
   ...
   ...
}
Everything enclosed by the //Begin_Html and //End_Html lines is considered to be pure HTML (to not confuse the C++ compiler the HTML block has to be enclosed by C style (/* ... */) comments.

Preferred Coding Style

Here we describe our preferred coding style. Coding style is very personal and we don't want to force our views on anybody. But for any contributions to the ROOT system that we have to maintain we would like you to follow our coding style.

Indentation

To be able to keep as much code as possible in the visible part of the editor of to avoid over abundant line wrapping we use indentation of 3 spaces. No tabs since they give the code always a different look depending on the tab settings of the original coder. If everything looks nicely lined up with a tab setting of 4 spaces, it does not look so nicely anymore when the tab setting is changed to 3, 5, etc. spaces.

Placing Braces and Spaces

The other issue that always comes up in C/C++ styling is the placement of braces and spaces. Unlike the indent size, there are few technical reasons to choose one placement strategy over the other, but the preferred way, as shown to us by the prophets Kernighan and Ritchie, is to put the opening brace last on the line, and put the closing brace first, thusly:

   if (x is true) {
      we do y
   }
However, there is one special case, namely functions: they have the opening brace at the beginning of the next line, thus:
int function(int x)
{
   body of function
}
Heretic people all over the world have claimed that this inconsistency is ... well ... inconsistent, but all right-thinking people know that (a) K&R are right and (b) K&R are right. Besides, functions are special anyway (you can't nest them in C/C++).

Note that the closing brace is empty on a line of its own, except in the cases where it is followed by a continuation of the same statement, ie a while in a do-statement or an else in an if-statement, like this:

   do {
      body of do-loop
   } while (condition);
and
   if (x == y) {
      ..
   } else if (x > y) {
      ...
   } else {
      ....
   }
Rationale: K&R.

Also, note that this brace-placement also minimizes the number of empty (or almost empty) lines, without any loss of readability. Thus, as the supply of new-lines on your screen is not a renewable resource (think 25-line terminal screens here), you have more empty lines to put comments on.

Notice also in the above examples the usage of spaces around keywords, operators and parenthesis/braces. Avoid the following free styles:

   if( x==y ){
or any derivative thereof.

In these cases indent -kr -i3 -ts255 is our best friend, for example code that we'll get looking like this:

int aap(int inp) {
   if( inp>0 ){
      return   0;
      int a = 1;
      if (inp==0 &&a==1) {
         printf("this is a very long line that is not yet ending", a, inp, a, inp, a  , inp);
         a+= inp;
         return a;
      }
   }
   else {
   return 1; }
 
   if(inp==0)return -1;
return 1;
}                 
You will find back like this:
int aap(int inp)
{
   if (inp > 0) {
      return 0;
      int a = 1;
      if (inp == 0 && a == 1) {
         printf("this is a very long line that is not yet ending", a, inp,
                a, inp, a, inp);
         a += inp;
         return a;
      }
   } else {
      return 1;
   }
 
   if (inp == 0)
      return -1;
   return 1;
}                                                                               

Where to go from here

For the rest read the Taligent Guide and use common sense.


Rene Brun, Fons Rademakers
Last update 28/10/99 by FR