Jump to: navigation, search

Difference between revisions of "CppCodingStandards"

(Fix Wiki formatting error (source tag requires a language). All the other sections use pre and nowiki tags.)
 
(8 intermediate revisions by 3 users not shown)
Line 1: Line 1:
__NOTOC__
+
 
 
<!-- ## page was renamed from [[CodingStandards]] -->
 
<!-- ## page was renamed from [[CodingStandards]] -->
 
= C++ Coding Standards =
 
= C++ Coding Standards =
Line 13: Line 13:
 
so we can clarify it and improve this document.
 
so we can clarify it and improve this document.
  
<<[[TableOfContents]]()>>
+
__TOC__
  
 
== Header Files ==
 
== Header Files ==
Line 90: Line 90:
 
Please always place a comment on the #endif indicating the include guard #define's label
 
Please always place a comment on the #endif indicating the include guard #define's label
  
=== Never Use `using namespace` in Header Files ===
+
=== Never Use using namespace in Header Files ===
  
 
You should never use a `using namespace` directive in a header file.
 
You should never use a `using namespace` directive in a header file.
Line 100: Line 100:
  
 
<pre><nowiki>#!highlight cpp
 
<pre><nowiki>#!highlight cpp
// /kernel/communication/Packet.h
+
// /kernel/communication/packet.h
 
#include <vector>
 
#include <vector>
 
namespace kernel
 
namespace kernel
Line 106: Line 106:
 
namespace communication
 
namespace communication
 
{
 
{
class Packet
+
class packet
 
{
 
{
 
public:
 
public:
   Packet();
+
   packet();
 
   /** Get internal buffer */
 
   /** Get internal buffer */
   std::vector<uint8_t> &buffer();
+
   std::vector<uint8_t>& get_buffer();
 
private:
 
private:
 
   std::vector<uint8_t> _buffer;
 
   std::vector<uint8_t> _buffer;
Line 124: Line 124:
  
 
<pre><nowiki>#!highlight cpp
 
<pre><nowiki>#!highlight cpp
// /kernel/communication/Packet.h
+
// /kernel/communication/packet.h
 
#include <vector>
 
#include <vector>
  
Line 133: Line 133:
 
namespace communication
 
namespace communication
 
{
 
{
class Packet
+
class packet
 
{
 
{
 
public:
 
public:
   Packet();
+
   packet();
 
   /** Get internal buffer */
 
   /** Get internal buffer */
   vector<uint8_t> &buffer();
+
   vector<uint8_t>& get_buffer();
 
private:
 
private:
 
   vector<uint8_t> _buffer;
 
   vector<uint8_t> _buffer;
Line 165: Line 165:
 
<pre><nowiki>#!highlight cpp
 
<pre><nowiki>#!highlight cpp
 
std::string my_data; // a string called my_data
 
std::string my_data; // a string called my_data
char const *ptr= my_data.c_str(); // a pointer to unmodifiable char array named ptr
+
char const* ptr = my_data.c_str(); // a pointer to unmodifiable char array named ptr
char const * const c_ptr= my_data.c_str(); // a non-modifiable pointer to  
+
char const* const c_ptr = my_data.c_str(); // a non-modifiable pointer to  
 
                                           // non-modifiable char array named c_ptr
 
                                           // non-modifiable char array named c_ptr
  
 
// a function accepting a reference to a non-modifiable string object
 
// a function accepting a reference to a non-modifiable string object
void fun(std::string const &str)
+
void fun(std::string const& str)
 
{
 
{
 
   ...
 
   ...
Line 184: Line 184:
 
Acceptable examples:
 
Acceptable examples:
  
 +
 +
<pre><nowiki>#!highlight cpp
 
::kernel
 
::kernel
 
::kernel::client
 
::kernel::client
 
::kernel::client::communication
 
::kernel::client::communication
 +
</nowiki></pre>
 +
  
 
=== Class Names ===
 
=== Class Names ===
 +
 +
'''FIXME: Desc says they should be PascalCased but example says they shouldn't.'''
  
 
Class names should be PascalCased and should adequately describe the
 
Class names should be PascalCased and should adequately describe the
Line 199: Line 205:
 
an adjective that illustrates the interface's main purpose.  For instance,
 
an adjective that illustrates the interface's main purpose.  For instance,
 
an abstract base/interface class that describes a class type that
 
an abstract base/interface class that describes a class type that
can be interrupted by a signal could be called "Interruptible"
+
can be interrupted by a signal could be called `interruptible`
  
 
Acceptable examples:
 
Acceptable examples:
Line 205: Line 211:
  
 
<pre><nowiki>#!highlight cpp
 
<pre><nowiki>#!highlight cpp
class SQLClient; // describes an object acting as a client to a SQL store
+
class sql_client; // describes an object acting as a client to a SQL store
class Interruptible; // an interface class describing a type of object that
+
class interruptible; // an interface class describing a type of object that
 
                         can be interrupted by some signal
 
                         can be interrupted by some signal
 
</nowiki></pre>
 
</nowiki></pre>
Line 215: Line 221:
  
 
<pre><nowiki>#!highlight cpp
 
<pre><nowiki>#!highlight cpp
class ClsClient; // Don't use useless prefixes!
+
class SqlClient; // Don't use PascalCased or camelCased names
class Tool; // Doesn't describe anything.  A tool which does '''''what'''''?
+
class cls_client; // Don't use useless prefixes!
 +
class tool; // Doesn't describe anything.  A tool which does '''''what'''''?
 
</nowiki></pre>
 
</nowiki></pre>
  
Line 237: Line 244:
 
{
 
{
 
public:
 
public:
   Student(std::string const &name,
+
   Student(std::string const& name,
 
           uint64_t id) :
 
           uint64_t id) :
 
     _name(name),
 
     _name(name),
Line 246: Line 253:
 
private:
 
private:
 
   std::string _name; ///< The student's name
 
   std::string _name; ///< The student's name
   uint64_t _id; ///< The student's identifer
+
   uint64_t _id; ///< The student's identifier
 
}
 
}
 
</nowiki></pre>
 
</nowiki></pre>
Line 254: Line 261:
  
 
Class methods should be lowercased, with underscore separation.  Of utmost
 
Class methods should be lowercased, with underscore separation.  Of utmost
importance is the fact that the method name should indicate an *action* that
+
importance is the fact that the method name should indicate an '''action''' that
describes the *action* that is performed by the method.
+
describes the '''action''' that is performed by the method.
  
 
==== Standardized Accessor and Mutator Method Pairing ====
 
==== Standardized Accessor and Mutator Method Pairing ====
Line 265: Line 272:
  
 
For const returns, name the accessor the same as the private member
 
For const returns, name the accessor the same as the private member
data variable, without the underscore prefix
+
data variable, prefixed with "get_".
 
 
For accessing pointers to mutable composite data, use the prefix of
 
"mutable_" along with the composite member data variable name
 
  
For regular, non-pointer setters, prefix the name of the private
+
For setters, prefix the name of the private
 
member data with "set_".
 
member data with "set_".
  
Line 280: Line 284:
  
 
<pre><nowiki>#!highlight cpp
 
<pre><nowiki>#!highlight cpp
   std::vector<Teacher *> _teachers;
+
   std::vector<teacher*> _teachers;
 
</nowiki></pre>
 
</nowiki></pre>
  
Line 289: Line 293:
  
 
<pre><nowiki>#!highlight cpp
 
<pre><nowiki>#!highlight cpp
   Teacher *teacher(size_t index);
+
   teacher* get_teacher(size_t index);
 
</nowiki></pre>
 
</nowiki></pre>
  
Line 298: Line 302:
  
 
<pre><nowiki>#!highlight cpp
 
<pre><nowiki>#!highlight cpp
   void add_teacher(Teacher *new_teacher);
+
   void add_teacher(teacher* new_teacher);
 
</nowiki></pre>
 
</nowiki></pre>
  
Line 306: Line 310:
  
 
<pre><nowiki>#!highlight cpp
 
<pre><nowiki>#!highlight cpp
class Teacher
+
class teacher
 
{
 
{
 
public:
 
public:
   Teacher(std::string const &name) :
+
   teacher(std::string const &name) :
 
     _name(name)
 
     _name(name)
 
   {}
 
   {}
   ~Teacher()
+
   ~teacher()
 
   {}
 
   {}
 
private:
 
private:
Line 318: Line 322:
 
};
 
};
  
class Student
+
class student
 
{
 
{
 
public:
 
public:
   Student(std::string const &name,
+
   student(std::string const &name,
 
           uint64_t id) :
 
           uint64_t id) :
 
     _name(name),
 
     _name(name),
 
     _id(id)
 
     _id(id)
 
   {}
 
   {}
   ~Student()
+
   ~student()
 
   {}
 
   {}
 
   /**
 
   /**
 
   * Returns the student's name
 
   * Returns the student's name
 
   */
 
   */
   std::string const &name() const
+
   std::string const& get_name() const
 
   {
 
   {
 
     return _name;
 
     return _name;
Line 338: Line 342:
 
   * Returns the student's id
 
   * Returns the student's id
 
   */
 
   */
   uint64_t id() const
+
   uint64_t get_id() const
 
   {
 
   {
 
     return id;
 
     return id;
Line 346: Line 350:
 
   * teacher or NULL if not set
 
   * teacher or NULL if not set
 
   */
 
   */
   Teacher const &homeroom_teacher() const
+
   teacher const& get_homeroom_teacher() const
 
   {
 
   {
 
     return *_homeroom_teacher;
 
     return *_homeroom_teacher;
Line 354: Line 358:
 
   * all the student's teachers
 
   * all the student's teachers
 
   */
 
   */
   std::vector<Teacher *> &teachers() const
+
   std::vector<teacher*>& get_teachers() const
 
   {
 
   {
 
     return _teachers;
 
     return _teachers;
Line 362: Line 366:
 
   * index
 
   * index
 
   */
 
   */
   Teacher const &teacher(size_t index) const
+
   teacher const& get_teacher(size_t index) const
 
   {
 
   {
 
     // note: NOT exception safe! Just an example!
 
     // note: NOT exception safe! Just an example!
Line 371: Line 375:
 
   * homeroom teacher
 
   * homeroom teacher
 
   */
 
   */
   void set_homeroom_teacher(Teacher *teacher)
+
   void set_homeroom_teacher(teacher* teacher)
 
   {
 
   {
 
     _homeroom_teacher = teacher;
 
     _homeroom_teacher = teacher;
Line 379: Line 383:
 
   * of teachers for this student.
 
   * of teachers for this student.
 
   */
 
   */
   void add_teacher(Teacher *teacher)
+
   void add_teacher(teacher* teacher)
 
   {
 
   {
 
     _teachers.push_back(teacher);
 
     _teachers.push_back(teacher);
Line 386: Line 390:
 
   std::string _name; ///< The student's name
 
   std::string _name; ///< The student's name
 
   uint64_t _id; ///< The student's identifer
 
   uint64_t _id; ///< The student's identifer
   Teacher *_homeroom_teacher; ///< The student's homeroom teacher
+
   teacher* _homeroom_teacher; ///< The student's homeroom teacher
   std::vector<Teacher *> _teachers; ///< All of the student's teachers
+
   std::vector<teacher*> _teachers; ///< All of the student's teachers
 
}
 
}
  
Line 399: Line 403:
  
 
{{{#!highlight cpp
 
{{{#!highlight cpp
class Engine
+
class engine
 
{
 
{
 
public:
 
public:
   Engine() :
+
   engine() :
 
     start_time(0)
 
     start_time(0)
 
   {}
 
   {}
Line 412: Line 416:
 
};
 
};
  
class V6Engine :public Engine
+
class v6_engine :public Engine
 
{
 
{
 
public:
 
public:
   V6Engine() :
+
   v6_engine() :
     Engine()
+
     engine()
 
   {}
 
   {}
   ~V6Engine() {}
+
   ~v6_engine() {}
 
private:
 
private:
 
   int do_start();
 
   int do_start();
 
};
 
};
  
int Engine::start()
+
int engine::start()
 
{
 
{
 
   // log the time the engine started
 
   // log the time the engine started
Line 431: Line 435:
 
}
 
}
  
int V6Engine::do_start()
+
int v6_engine::do_start()
 
{
 
{
 
   // start the engine and return the
 
   // start the engine and return the
Line 441: Line 445:
 
=== Enums ===
 
=== Enums ===
  
The names of enums should be lowercase and end with a "_t" suffix to
+
The names of enums should be lowercase with underscore separation.
designate they are a type.
 
  
 
Example:
 
Example:
Line 448: Line 451:
  
 
<pre><nowiki>#!highlight cpp
 
<pre><nowiki>#!highlight cpp
enum option_t
+
enum option
 
{
 
{
 
   DEFAULT = 0, // the default option
 
   DEFAULT = 0, // the default option
Line 455: Line 458:
 
};
 
};
  
option_t my_option = DEFAULT;
+
option my_option = DEFAULT;
 
</nowiki></pre>
 
</nowiki></pre>
  
Line 467: Line 470:
 
is valid, use:
 
is valid, use:
  
<source>
+
<pre><nowiki>
 
bool is_valid;
 
bool is_valid;
 
bool has_drivers;
 
bool has_drivers;
Line 476: Line 479:
 
and not:
 
and not:
  
<source>
+
<pre><nowiki>
 
bool valid;
 
bool valid;
 
bool drivers;
 
bool drivers;
Line 510: Line 513:
 
std::string const DEFAULT_DATA_DIRECTORY = "/var";
 
std::string const DEFAULT_DATA_DIRECTORY = "/var";
  
class Client
+
class client
 
{
 
{
 
public:
 
public:
Line 536: Line 539:
 
Example:
 
Example:
  
Assume that you are coding a class named Client that exists in the  
+
Assume that you are coding a class named `client` that exists in the  
::kernel::communication namespace.   
+
`kernel::communication` namespace.   
  
 
The header and source files respectively should be:
 
The header and source files respectively should be:
  
/kernel/communication/Client.h
+
/kernel/communication/client.h
/kernel/communication/Client.cc
+
/kernel/communication/client.cc
  
 
== Indentation and Formatting ==
 
== Indentation and Formatting ==
Line 556: Line 559:
 
namespace { } blocks and scope-specifiers such as private: should not be indented.
 
namespace { } blocks and scope-specifiers such as private: should not be indented.
  
switch statements should indent case labels one indentation level.
+
switch statements should '''NOT''' indent case labels.
  
 
Example:
 
Example:
Line 567: Line 570:
 
{
 
{
  
enum option_t
+
enum option
 
{
 
{
 
   OPTION_ONE = 1,
 
   OPTION_ONE = 1,
Line 574: Line 577:
  
 
bool some_boolean_variable = false;
 
bool some_boolean_variable = false;
option_t some_option = OPTION_TWO;
+
option some_option = OPTION_TWO;
  
class Client
+
class client
 
{
 
{
 
public:
 
public:
   Client()
+
   client()
 
   {
 
   {
 
     if (not some_boolean_variable)
 
     if (not some_boolean_variable)
Line 585: Line 588:
 
       switch (some_option)
 
       switch (some_option)
 
       {
 
       {
        case OPTION_ONE:
+
      case OPTION_ONE:
         {
+
         // do option one and fall through...
          // do option one
+
      case OPTION TWO:
         }
+
         // do option two
         default:
+
         break;
         {
+
      default:
          // do default action
+
         // do default action
        }
 
 
       }
 
       }
 
     }
 
     }
Line 633: Line 635:
 
===== Pointer and Reference Variables =====
 
===== Pointer and Reference Variables =====
  
When declaring a pointer variable or argument, place the asterisk adjacent to the variable name. For instance:
+
When declaring a pointer variable or argument, place the asterisk adjacent to the type. The idea
 +
here is to keep type information together.
 +
 
 +
For instance:
  
  
 
<pre><nowiki>#!highlight cpp
 
<pre><nowiki>#!highlight cpp
string *foo;
+
string* foo;
 
</nowiki></pre>
 
</nowiki></pre>
  
Line 647: Line 652:
  
 
<pre><nowiki>#!highlight cpp
 
<pre><nowiki>#!highlight cpp
string &foo;
+
string& foo;
 
</nowiki></pre>
 
</nowiki></pre>
  
Line 737: Line 742:
 
{
 
{
 
public:
 
public:
   MySingleton &singleton()
+
   MySingleton& singleton()
 
   {
 
   {
 
     static MySingleton my_object;
 
     static MySingleton my_object;
Line 761: Line 766:
 
{
 
{
 
public:
 
public:
   std::vector<Teacher *> &teachers();
+
   std::vector<Teacher*>& teachers();
 
private:
 
private:
   std::vector<Teacher *> _teachers;
+
   std::vector<Teacher*> _teachers;
 
};
 
};
 
</nowiki></pre>
 
</nowiki></pre>
Line 777: Line 782:
 
{
 
{
 
public:
 
public:
   typedef std::vector<Teacher *> Teachers;
+
   typedef std::vector<Teacher*> Teachers;
   Teachers &teachers();
+
   Teachers& teachers();
 
private:
 
private:
 
   Teachers _teachers;
 
   Teachers _teachers;
Line 842: Line 847:
 
#include <boost/scoped_ptr.hpp>
 
#include <boost/scoped_ptr.hpp>
  
class MyClass
+
class my_class
 
{
 
{
 
public:
 
public:
   MyClass() {}
+
   my_class() {}
   ~MyClass() {]
+
   ~my_class() {]
 
   void do_something()
 
   void do_something()
 
   {
 
   {
Line 855: Line 860:
 
void example_scoped()
 
void example_scoped()
 
{
 
{
   boost::shared_ptr<MyClass> my_object(new MyClass());
+
   boost::shared_ptr<my_class> my_object(new my_class());
 
   my_object.do_something();
 
   my_object.do_something();
   SomeClass *my_ptr_to_object= my_object.get();
+
   my_class* my_ptr_to_object= my_object.get();
 
   my_ptr_to_object->do_something();
 
   my_ptr_to_object->do_something();
 
}
 
}
Line 885: Line 890:
  
 
<pre><nowiki>#!highlight cpp
 
<pre><nowiki>#!highlight cpp
class Foo
+
class foo
 
{
 
{
 
public:
 
public:
Line 891: Line 896:
 
};
 
};
  
inline void Foo::bar()
+
inline void foo::bar()
 
{
 
{
 
  /* do something */
 
  /* do something */
Line 907: Line 912:
  
 
<pre><nowiki>#!highlight cpp
 
<pre><nowiki>#!highlight cpp
class MyClass
+
class my_class
 
{
 
{
 
public:
 
public:
   MyClass(uint32_t number_1, uint32_t number_2) :
+
   my_class(uint32_t number_1, uint32_t number_2) :
 
     _number_1(number_1),
 
     _number_1(number_1),
 
     _number_2(number_2)
 
     _number_2(number_2)
Line 925: Line 930:
  
 
<pre><nowiki>#!highlight cpp
 
<pre><nowiki>#!highlight cpp
class MyClass
+
class my_class
 
{
 
{
 
public:
 
public:
   MyClass(uint32_t number_1, uint32_t number_2)
+
   my_class(uint32_t number_1, uint32_t number_2)
 
   {
 
   {
 
     _number_1 = number_1;
 
     _number_1 = number_1;
Line 976: Line 981:
  
 
<pre><nowiki>#!highlight cpp
 
<pre><nowiki>#!highlight cpp
// Header file /kernel/communication/Client.h
+
// Header file /kernel/communication/client.h
  
 
namespace kernel
 
namespace kernel
Line 983: Line 988:
 
{
 
{
  
class Client
+
class client
 
{
 
{
 
   ...
 
   ...
Line 991: Line 996:
 
} // namespace kernel
 
} // namespace kernel
  
// Source file /kernel/communication/Client.cc
+
// Source file /kernel/communication/client.cc
  
 
</nowiki></pre>
 
</nowiki></pre>
Line 1,018: Line 1,023:
  
 
<pre><nowiki>#!highlight cpp
 
<pre><nowiki>#!highlight cpp
enum return_t
+
enum result
 
{
 
{
 
   SUCCESS = 0,
 
   SUCCESS = 0,
Line 1,078: Line 1,083:
 
reside.
 
reside.
  
For instance, if a source file `/kernel/client/Client.h` exists,
+
For instance, if a source file `/kernel/client/client.h` exists,
containing a class "Client", the namespacing should be:
+
containing a class "client", the namespacing should be:
  
 
namespace kernel
 
namespace kernel
Line 1,085: Line 1,090:
 
namespace client
 
namespace client
 
{
 
{
class Client { ... };
+
class client { ... };
 
} // namespace client
 
} // namespace client
 
} // namespace kernel
 
} // namespace kernel
Line 1,149: Line 1,154:
 
<pre><nowiki>#!highlight cpp
 
<pre><nowiki>#!highlight cpp
 
/**
 
/**
  * @file
+
  * An example header file.
*  example.h
 
*
 
* @brief
 
An example header file.
 
 
  *
 
  *
 
  * @details
 
  * @details
Line 1,187: Line 1,188:
 
  * More detailed description of myVar that works because of JAVADOC_AUTOBRIEF.
 
  * More detailed description of myVar that works because of JAVADOC_AUTOBRIEF.
 
  */
 
  */
int myVar;
+
int my_var;
 
</nowiki></pre>
 
</nowiki></pre>
  
Line 1,196: Line 1,197:
  
 
<pre><nowiki>#!highlight cpp
 
<pre><nowiki>#!highlight cpp
int myVar; ///< A brief description of myVar
+
int my_var; ///< A brief description of my_var
  
int myVar2; ///< This is a detailed description of myVar2 because it
+
int my_var2; ///< This is a detailed description of my_var2 because it
            ///< spans multiple lines.
+
            ///< spans multiple lines.
 
</nowiki></pre>
 
</nowiki></pre>
  
Line 1,208: Line 1,209:
 
<pre><nowiki>#!highlight cpp
 
<pre><nowiki>#!highlight cpp
 
/**
 
/**
  * @brief
+
  * A brief description of HolyHandGrenade.
A brief description of HolyHandGrenade.
 
 
  *
 
  *
 
  * @details
 
  * @details
 
  *  An even more detailed description of HolyHandGrenade.
 
  *  An even more detailed description of HolyHandGrenade.
 
  */
 
  */
class HolyHandGrenade
+
class holy_hand_grenade
 
{
 
{
 
private:
 
private:
   int grenadeSize;  ///< Specifies if you want a large or small grenade
+
   int grenade_size;  ///< Specifies if you want a large or small grenade
  
 
public:
 
public:
 
   /**
 
   /**
   * @brief
+
   * Hurls thine Holy Hand Grenade towards thy foe.
  *  Hurl thine Holy Hand Grenade towards thy foe.
 
 
   *
 
   *
   * @details
+
   * @detail
 
   *  Mercifully blows thine enemies to tiny bits.
 
   *  Mercifully blows thine enemies to tiny bits.
 
   *
 
   *
Line 1,238: Line 1,237:
 
== Function and Method Comments ==
 
== Function and Method Comments ==
  
Every function should have a @brief section and, if appropriate, a @detail
+
Every function can have a @detail
section that describes the function more in-depth.
+
section that describes the function more in-depth if needed.
  
 
Every parameter should be commented. Please try to use the direction attribute
 
Every parameter should be commented. Please try to use the direction attribute
Line 1,254: Line 1,253:
 
<pre><nowiki>#!highlight cpp
 
<pre><nowiki>#!highlight cpp
 
/**
 
/**
  * @brief
+
  * Returns the sum of two positive integers.
*  Return the sum of two positive integers.
 
 
  *
 
  *
  * @details
+
  * @detail
 
  *  Adds x and y and returns the result in z.
 
  *  Adds x and y and returns the result in z.
 
  *
 
  *

Latest revision as of 22:42, 5 August 2013

C++ Coding Standards

Note that coding standards and guidelines will never be perfect and that not everyone will agree with every guideline or naming convention. The purpose of the guidelines and standards are to maintain consistency in the source code.

In general, do the most consistent thing given the existing code base. If something is not immediately obvious, is ambiguous, or if you feel is wrong, please bring it up on the mailing list or in IRC so we can clarify it and improve this document.

Contents

Header Files

Keep #include directives to a minimum in header files. Prefer forward declaring classes/structs if at all possible.

Don't use an #include when a forward declaration would suffice.

While includes should be kept to a minimum, if something is used in a file and cannot be forward declared, it should be explicitly included. This is especially relevant for things such as std::string which might be sucked in from another source. (There is a cpplint.py check for this)

All files, headers and implementation, should include everything they need to be self-sufficient. They should never assume something will be pre-included.

All implementation files (.cc) should include `config.h` FIRST and relevant header files, that are referenced by the implementation file.

For #include'ing header files that are in a local directory, use this form:


#!highlight cpp
#include "kernel/communication/Client.h"


For #include'ing system headers or library header files, use the form:


#!highlight cpp
#include <somelib/some_lib_header.h>


Do not make header files that consist only of other header files.

Use C++ includes, not C includes

Use C++ includes, not C ones. For instance, you should use:


#!highlight cpp
#include <cstdio>
#include <cstring>


and not:


#!highlight cpp
#include <stdio.h>
#include <string.h>


Include Guards

All headers must use include guards. The name of the include guard #define should be the file path from the source root, in all uppercase, with underscore separation.

For instance, if you are editing the file `/kernel/communication/Client.h`, you would use the following:


#!highlight cpp
#ifndef KERNEL_COMMUNICATION_CLIENT_H
#define KERNEL_COMMUNICATION_CLIENT_H
...
#endif /* KERNEL_COMMUNICATION_CLIENT_H */


Please always place a comment on the #endif indicating the include guard #define's label

Never Use using namespace in Header Files

You should never use a `using namespace` directive in a header file.

Always specify namespace prefixes in header files, even for std:: symbols.

Correct:


#!highlight cpp
// /kernel/communication/packet.h
#include <vector>
namespace kernel
{
namespace communication
{
class packet
{
public:
  packet();
  /** Get internal buffer */
  std::vector<uint8_t>& get_buffer();
private:
  std::vector<uint8_t> _buffer;
};
} // namespace communication
} // namespace kernel


Incorrect:


#!highlight cpp
// /kernel/communication/packet.h
#include <vector>

using namespace std;

namespace kernel
{
namespace communication
{
class packet
{
public:
  packet();
  /** Get internal buffer */
  vector<uint8_t>& get_buffer();
private:
  vector<uint8_t> _buffer;
};
} // namespace communication
} // namespace kernel


Even better, see the section on typedef'ing :)

Variable Declaration and Naming Standards

Variable Declaration Order

Always think about and read declarations right to left.

If something is a reference or pointer to non-modifiable data, you should structure the declaration like so:

type [data-const-modifier] [pointer-or-reference] [pointer-const-modifier] symbol-name

For example:


#!highlight cpp
std::string my_data; // a string called my_data
char const* ptr = my_data.c_str(); // a pointer to unmodifiable char array named ptr
char const* const c_ptr = my_data.c_str(); // a non-modifiable pointer to 
                                           // non-modifiable char array named c_ptr

// a function accepting a reference to a non-modifiable string object
void fun(std::string const& str)
{
  ...
}


Namespace Names

Namespaces should be all lowercased, with preference to single words. If a namespace must be dual-worded, use underscores.

Acceptable examples:


#!highlight cpp
::kernel
::kernel::client
::kernel::client::communication


Class Names

FIXME: Desc says they should be PascalCased but example says they shouldn't.

Class names should be PascalCased and should adequately describe the object, with as little abbreviation as possible. Where necessary, acronym'd parts of a class name should be kept in all uppercase.

Prefixing (such as prefixing all classes with Cls) is to be avoided.

For abstract base classes, it is encouraged to name the class with an adjective that illustrates the interface's main purpose. For instance, an abstract base/interface class that describes a class type that can be interrupted by a signal could be called `interruptible`

Acceptable examples:


#!highlight cpp
class sql_client; // describes an object acting as a client to a SQL store
class interruptible; // an interface class describing a type of object that
                        can be interrupted by some signal


Poor examples:


#!highlight cpp
class SqlClient; // Don't use PascalCased or camelCased names
class cls_client; // Don't use useless prefixes!
class tool; // Doesn't describe anything.  A tool which does '''''what'''''?


Class Member Variable Names

Note: Please see Scoping for reasons why all member data should be private.

Private Class Member Data

Private member data variables should be prefixed with an underscore and should be all lowercase with underscore separation.

Example:


#!highlight cpp
class Student
{
public:
  Student(std::string const& name,
          uint64_t id) :
    _name(name),
    _id(id)
  {}
  ~Student()
  {}
private:
  std::string _name; ///< The student's name
  uint64_t _id; ///< The student's identifier
}


Class Method Names

Class methods should be lowercased, with underscore separation. Of utmost importance is the fact that the method name should indicate an action that describes the action that is performed by the method.

Standardized Accessor and Mutator Method Pairing

Use the following naming convention for public accessor/mutator pairs for private member data:

Accessors:

For const returns, name the accessor the same as the private member data variable, prefixed with "get_".

For setters, prefix the name of the private member data with "set_".

For aggregate composition of member data (when member data is of a container type), provide appropriately-indexed accessors that match the contained composite data type. For instance, if a class has a private member:


#!highlight cpp
  std::vector<teacher*> _teachers;


You should provide accessor methods to the Teacher pointer members like so:


#!highlight cpp
  teacher* get_teacher(size_t index);


For adding elements to such composite members, prefix adder methods with "add_" like so:


#!highlight cpp
  void add_teacher(teacher* new_teacher);


Continuing the example from the previous section:


#!highlight cpp
class teacher
{
public:
  teacher(std::string const &name) :
    _name(name)
  {}
  ~teacher()
  {}
private:
  std::string _name; ///< The teacher's name
};

class student
{
public:
  student(std::string const &name,
          uint64_t id) :
    _name(name),
    _id(id)
  {}
  ~student()
  {}
  /**
   * Returns the student's name
   */
  std::string const& get_name() const
  {
    return _name;
  }
  /**
   * Returns the student's id
   */
  uint64_t get_id() const
  {
    return id;
  }
  /**
   * Returns a pointer to the student's homeroom
   * teacher or NULL if not set
   */
  teacher const& get_homeroom_teacher() const
  {
    return *_homeroom_teacher;
  }
  /**
   * Returns a reference to a container of
   * all the student's teachers
   */
  std::vector<teacher*>& get_teachers() const
  {
    return _teachers;
  }
  /**
   * Returns a specific teacher at a supplied
   * index
   */
  teacher const& get_teacher(size_t index) const
  {
    // note: NOT exception safe! Just an example!
    return *(_teachers[index]);
  }
  /**
   * Returns a pointer to the student's
   * homeroom teacher
   */
  void set_homeroom_teacher(teacher* teacher)
  {
    _homeroom_teacher = teacher;
  }
  /**
   * Adds a new teacher to the container
   * of teachers for this student.
   */
  void add_teacher(teacher* teacher)
  {
    _teachers.push_back(teacher);
  }
private:
  std::string _name; ///< The student's name
  uint64_t _id; ///< The student's identifer
  teacher* _homeroom_teacher; ///< The student's homeroom teacher
  std::vector<teacher*> _teachers; ///< All of the student's teachers
}

==== Private Pure Virtual Implementation Method Names ====

If a public interface requires virtualization be implemented via private, pure-
virtual methods, one should name the pure virtual implementation method the same
as the public method, prefixed with "do_"

For instance:

{{{#!highlight cpp
class engine
{
public:
  engine() :
    start_time(0)
  {}
  virtual ~Engine() {}
  int start();
private:
  virtual int do_start() = 0;
  time_t start_time;
};

class v6_engine :public Engine
{
public:
  v6_engine() :
    engine()
  {}
  ~v6_engine() {}
private:
  int do_start();
};

int engine::start()
{
  // log the time the engine started
  start_time = time(NULL);
  // call subclass' private implementation
  return do_start_time();
}

int v6_engine::do_start()
{
  // start the engine and return the
  // results of starting the engine...
}


Enums

The names of enums should be lowercase with underscore separation.

Example:


#!highlight cpp
enum option
{
  DEFAULT = 0, // the default option
  MINIMUM = 1, // the minimum option
  MAXIMUM = 2 // the maximum option
};

option my_option = DEFAULT;


Boolean Variables

Boolean variables should have a prefix which indicates their "booleanness" and should be a verb.

For example, if you have a variable that describes whether something is valid, use:

bool is_valid;
bool has_drivers;
bool can_be_empty;


and not:

bool valid;
bool drivers;
bool emptiness;


Module/Global Variable Names

Variables that exist at the global scope should generally be discouraged, however the naming of such module-level or global variables should be lowercased, with underscore separation.

Example:

uint32_t my_global_option;

Note:

Constants are not variables and follow a separate naming convention

Constant Names

The names of constants should be in all uppercase, regardless of the constant's scope.

There should be no prefixing of constants with unnecessary type information.

Acceptable examples:


#!highlight cpp
std::string const DEFAULT_DATA_DIRECTORY = "/var";

class client
{
public:
  uint32_t const DEFAULT_PORT = 9999;
};


Incorrect examples:

#!highlight cpp
std::string const STR_DEFAULT_DATA_DIRECTORY = "/var"; // Uses unnecessary prefix
std::string const default_data_directory = "/var"; // Does not use all uppercase

Source Filenames and Directory Structure

Directories should match the namespaces that compose the program.

Headers should end with ".h" and source files should end with ".cc"

Source files and headers should be named the same as the class and namespace that is contained in the file.

Example:

Assume that you are coding a class named `client` that exists in the `kernel::communication` namespace.

The header and source files respectively should be:

/kernel/communication/client.h /kernel/communication/client.cc

Indentation and Formatting

Indentation

TAB characters should be eliminated from all source files.

For Vi(m) users, use the expandtab option

Indentation should be 2 spaces exactly at all indentation levels

Every block of code except namespaces and scope-specifiers should be indented a single level. namespace { } blocks and scope-specifiers such as private: should not be indented.

switch statements should NOT indent case labels.

Example:


#!highlight cpp
namespace kernel
{
namespace communication
{

enum option
{
  OPTION_ONE = 1,
  OPTION_TWO = 2
};

bool some_boolean_variable = false;
option some_option = OPTION_TWO;

class client
{
public:
  client()
  {
    if (not some_boolean_variable)
    {
      switch (some_option)
      {
      case OPTION_ONE:
        // do option one and fall through...
      case OPTION TWO:
        // do option two
        break;
      default:
        // do default action
      }
    }
  }
}
} // namespace communication
} // namespace kernel


Spacing

Variable Declarations

Use a single space between the variable's type and the variable's label (name).

Do not align variable labels on indentation levels as this indentation invariably gets out-of-line as the code is modified.

Correct:


#!highlight cpp
bool is_derived;
uint64_t num_derivatives;


Incorrect:


#!highlight cpp
bool  is_derived; // There should not be more than one space between type and label

uint64_t num_sizes; // Do not align variable labels on 
bool     has_size; // indentation levels


Pointer and Reference Variables

When declaring a pointer variable or argument, place the asterisk adjacent to the type. The idea here is to keep type information together.

For instance:


#!highlight cpp
string* foo;


Use `NULL` when referring to the null pointer, not `0`.

When declaring a reference variable or argument, place the ampersand adjacent to the variable name. For instance:


#!highlight cpp
string& foo;


Assignment Operators

One space before and one space after assignment operators.

Do not align assignment variables on indentation levels, since such indentation inevitably gets out-of-line as the code is modified.

Correct:

bool my_bool = false; uint32_t my_int = 0;

my_int += 1;

Incorrect:

bool my_bool= false; // There should be one space before assignment operator

uint32_t num_sizes = 0; // Do not align assignments on an uint64_t num_red_sizes= 0; // indentation level/tab line

Comparison Operators

When testing for comparisons, be as descriptive and verbose as possible, and use a space between the negation operator.

For instance, prefer this:


#!highlight cpp
if (can_print == false) {...};


or this:


#!highlight cpp
if (not can_print) {...}


to this:


#!highlight cpp
if (!can_print) {..};


Design Guidelines

Keep Methods/Functions Short

Long functions are sometimes appropriate, so no hard limit is placed on functions length. If a function exceeds about 40 lines, think about whether it can be broken up without harming the structure of the program.

Even if your long function works perfectly now, someone modifying it in a few months may add new behavior. This could result in bugs that are hard to find. Keeping your functions short and simple makes it easier for other people to read and modify your code.

You could find long and complicated functions when working with some code. Do not be intimidated by modifying existing code: if working with such a function proves to be difficult, you find that errors are hard to debug, or you want to use a piece of it in several different contexts, consider breaking up the function into smaller and more manageable pieces.

In summary, prefer functions that are small and focused.

Avoid Global Static Class Instances

Avoid global static class instances because of initialization order ambivalence. If you need a singleton object, use a public static class method named singleton() that initializes a method-scoped static object and returns that object. Ensure the singleton class' constructor is private to avoid any other way of creating the object.

Example:


#!highlight cpp
class MySingleton
{
public:
  MySingleton& singleton()
  {
    static MySingleton my_object;
    return my_object;
  }
private:
  MySingleton();
};


Liberal Use of `typedef`

For readability, make liberal use of `typedef`, especially in the case of STL container types inside classes.

For instance, let's assume this code:


#!highlight cpp
class Teacher;
class Student
{
public:
  std::vector<Teacher*>& teachers();
private:
  std::vector<Teacher*> _teachers;
};


The above code is more readable and maintainable when a `typedef` is used for the `std::vector<Teacher *>` as shown below:


#!highlight cpp
class Teacher;
class Student
{
public:
  typedef std::vector<Teacher*> Teachers;
  Teachers& teachers();
private:
  Teachers _teachers;
};


The `typedef` makes it easier to read and makes future possible modifications to what is a collection of Teachers easier (for instance, changing `std::vector<>` to `std::list<>`)

Class Design

Some helpful suggestions and best practices from Scott Meyers, Herb Sutter, and Andrei Alexandrescu:

  • Make interfaces easy to use correctly and hard to use incorrectly
  • Treat class design as type design
  • Prefer pass-by-reference-to-const to pass-by-value
  • Don't try to return a reference when you must return an object
  • Declare data members private
 except in behaviourless aggregates (C-style structs)
  • Prefer non-member non-friend functions to member functions
  • Declare non-member functions when type conversion should apply to all parameters
  • Consider support for a non-throwing swap
  • Be clear what kind of class you're writing
  • Prefer minimal classes to monolithic classes
  • Prefer composition to inheritance
  • Avoid inheriting from classes that were not designed to be base classes
  • Prefer providing abstract interfaces
  • Public inheritance models "is a"
  • Private inheritance models "is implemented in terms of"
  • Public inheritance is substitutability. Inherit, not to reuse, but to be reused
  • Practive safe overriding
  • Consider making virtual functions nonpublic, and public functions nonvirtual
  • Avoid providing implicit conversions
  • Don't give away your internals
  • Pimpl judiciously
  • Always provide new and delete together
  • If you provide any class-specific new,
 provide all of the standard forms (plain, in-place, and nothrow)

Always Use RIIA And Understand Who Owns What Memory/Resources

Never use malloc and free. Use C++'s new operator coupled with smart pointer containers.

When calling new, place the returned pointer to a resource into either a boost::shared_ptr<> or a boost::scoped_ptr<>. Doing so ensures that resources will be properly freed and that you do not need to call delete yourself.

Always put shared_ptr<> object construction on a separate code line to avoid problems with unnamed temporaries.

Example:


#!highlight cpp
// Example of scoped_ptr<> usage for a new'd object
// that should always be deleted at the end of a function

#include <boost/scoped_ptr.hpp>

class my_class
{
public:
  my_class() {}
  ~my_class() {]
  void do_something()
  {
    cout << "did something" << endl;
  }
};

void example_scoped()
{
  boost::shared_ptr<my_class> my_object(new my_class());
  my_object.do_something();
  my_class* my_ptr_to_object= my_object.get();
  my_ptr_to_object->do_something();
}


For objects that are shared by multiple threads of execution or different owners, use boost::shared_ptr<>.

Implement the Pimpl idiom using `boost::shared_ptr<>`

For more information on smart pointers, see this reference

Make Things As Const as Possible

Make methods that do not modify underlying member data const as much as possible.

Move Inline Method Bodies Out of Class Definitions

Instead of inlining method bodies in a class definition, instead declare the method regularly and define it in the header file below the class definition with an inline specifier.

Example:


#!highlight cpp
class foo
{
public:
 void bar();
};

inline void foo::bar()
{
 /* do something */
}


Use Initializer Lists Properly!

Initialize member data using initializer lists, instead of using assignment of member data in a constructor's body.

Correct:


#!highlight cpp
class my_class
{
public:
  my_class(uint32_t number_1, uint32_t number_2) :
    _number_1(number_1),
    _number_2(number_2)
  {}
private:
  uint32_t _number_1;
  uint32_t _number_2;
};


Incorrect:


#!highlight cpp
class my_class
{
public:
  my_class(uint32_t number_1, uint32_t number_2)
  {
    _number_1 = number_1;
    _number_2 = number_2;
  }
private:
  uint32_t _number_1;
  uint32_t _number_2;
};


Declaration Order

Your class definition should start with its public: section, followed by its protected: section and then its private: section. If any of these sections are empty, omit them.

Reuse of Open Source Libraries

When presented with a choice between writing your own code and re-using an open source library that already does what you want to do, in general you should re-use the open source library.

Libraries you should use whenever possible:

Boost C++ libraries and components:

 boost::program_options
 boost::any
 boost::thread
 boost::regex
 boost::asio
 boost::smart_ptr

Google Protobuffers gettext C++0x and the STL C++0x atomic<>

Using Namespaces Properly

Code that lives inside a specific module or category should reside inside a namespace indicating the module's functionality. In both header and source files for such code, the code should be encapsulated inside namespace { } blocks.

Example:


#!highlight cpp
// Header file /kernel/communication/client.h

namespace kernel
{
namespace communication
{

class client
{
  ...
};

} // namespace communication
} // namespace kernel

// Source file /kernel/communication/client.cc


NEVER place include statements inside of a namespace block.

Exception Handling

Use exceptions freely, but wisely. Exceptions should be reserved for catching exceptional behaviour, not naturally-occurring or expected errors.

Make try ... catch blocks as small in scope as possible.

Error Return/Retrieval

Do not return integer error or success codes.

Instead, use an enum that adequately describes the error/success returns and helps to clearly document the code.

Do NOT use #defines. Use an enum. After all, we're coding in C++, not C. :)

Example:


#!highlight cpp
enum result
{
  SUCCESS = 0,
  ERROR_IO = 1, // Error occurred doing I/O
  ERROR_LOGIC = 2, // There was a logical error...
};


Consider also using boost::system::error_code objects for common error returns from system calls.

Make Liberal Use of `assert`s

Make liberal use of asserts in your code.

However, be sure not to have any side-effects in your assert()s!

For instance, the following contrived example has a problematic side effect:


#!highlight cpp
void some_function()
{
  size_t x, y;

  for (x = 0, y = 0; x < 10; ++x)
  {
    assert((y = (x + (y - 1))) > x);
    cout << y;
  }
}


The side-effect is that the y variable is being assigned to in the assert() statement. Depending on whether asserts are compiled out of the source code, the output of the function is different.

Use C++-style Casts

Avoid using C-style casts. Use C++-style casts instead, which are more explicit and sometimes safer to use.

Example:


#!highlight cpp
// cast between integer types
uint32_t my_number = 100;
int32_t my_signed_number = static_cast<int32_t>(my_number);


Namespacing

All code should be namespaced properly into namespaces representing the directory structure in which the classes/functions reside.

For instance, if a source file `/kernel/client/client.h` exists, containing a class "client", the namespacing should be:

namespace kernel { namespace client { class client { ... }; } // namespace client } // namespace kernel

Types

Use standard integer and limit types defined in <cstdint> and <climit>

Prefer explicitly sized integer types, such as int64_t, over non-explicitly-sized integer types, such as long.

Use size_t when you need an unsigned integer type designating size, length, or capacity.

Use ssize_t when you need a signed integer type designating a return from a read() or write() call that may return a value less than 0 in case of an error.

When you need a size type that is platform-specific, use size_t and ssize_t.

Use off_t for file positions/offsets.

Use ptrdiff_t for integers representing offset or difference between pointers.

Code Documentation and Commenting

Comment Style

We will be using Doxygen to generate on-line source code documentation. Doxygen is very versatile and supports several different styles of commenting. In order to have some consistency in the code, below is the recommended commenting style.

Preceed Doxygen commands with the at-sign (@) instead of the backslash (\). E.g.:


#!highlight cpp
@brief
@details


Use the Javadoc style of commenting for multi-line comment blocks. For example:

#!highlight cpp
/**
 *  ...text...
 */


Note: The JAVADOC_AUTOBRIEF Doxygen option will be used.

File Comments

Documenting a source file is recommended, but is absolutely necessary if you want to document a global object (function, typedef, enum, macro, etc.). Otherwise, the documentation for the global object will not be generated.

A file should be commented at the beginning of the file.

Example:


#!highlight cpp
/**
 * An example header file.
 *
 * @details
 *   A more detailed description here.
 */


Class Comments

All classes should be commented immediately preceeding the class definition in the header file.

Class Methods

The methods of the class should be commented within the header file, not the implementation file. The API of the class should be clearly exposed through the header file only. Describe what the method does, what its parameters are, and what it returns. If there are complex details about the implementation that you feel need documenting, do so inside the method in the implementation file.

Also see comments in the #Function and Method Comments section.

Class Member Variables

Member variables should be commented in the header, when appropriate. Members can be commented either above the variable declaration:


#!highlight cpp
/**
 * Brief description of myVar.
 * More detailed description of myVar that works because of JAVADOC_AUTOBRIEF.
 */
int my_var;


Or, the member variables may be commented on the same line as the variable declaration:


#!highlight cpp
int my_var; ///< A brief description of my_var

int my_var2; ///< This is a detailed description of my_var2 because it
             ///< spans multiple lines.


Class Example

#!highlight cpp
/**
 * A brief description of HolyHandGrenade.
 *
 * @details
 *   An even more detailed description of HolyHandGrenade.
 */
class holy_hand_grenade
{
private:
  int grenade_size;   ///< Specifies if you want a large or small grenade

public:
  /**
   * Hurls thine Holy Hand Grenade towards thy foe.
   *
   * @detail
   *   Mercifully blows thine enemies to tiny bits.
   *
   * @param[in] count The number of the counting.
   */
  void hurl(int count);

  ...
};


Function and Method Comments

Every function can have a @detail section that describes the function more in-depth if needed.

Every parameter should be commented. Please try to use the direction attribute of the @param command ([in], [out], [in,out]).

If multiple return values are possible, it is preferable to use @retval to define each possible value that may be returned instead of @return. If there are many return values, or you just want to summarize what is returned, use @return to describe the return value.

Example:


#!highlight cpp
/**
 * Returns the sum of two positive integers.
 *
 * @detail
 *   Adds x and y and returns the result in z.
 *
 * @param[in] x First integer
 * @param[in] y Second integer
 * @param[out] z Holds the result of x+y
 *
 * @retval 0 success
 * @retval 1 failure, ints were not positive
 */
int sum(int x, int y, int *z)
{
  if (x < 0 || y < 0)
    return 1;

  *z = x + y;

  return 0;
}