C++ style guide: Difference between revisions

Jump to navigation Jump to search
5,049 bytes added ,  6 September 2021
Add separator recommendation between member functions and variables.
(import more text from the manual)
(Add separator recommendation between member functions and variables.)
(34 intermediate revisions by 5 users not shown)
Line 7: Line 7:


== Formatting ==
== Formatting ==
=== Line Length ===
Maximal length of source lines is 79 characters.


=== Indentation ===
=== Indentation ===


Use only spaces, and indent 2 spaces at a time.
* Use only spaces.
* Tabs are prohibited.
* Indent with 2 spaces at a time.


We use spaces for indentation. Absolutely do not use tabs in your code.
==== Control structures (if, while, ...) ====
You should probably set your editor to emit spaces when you hit the tab key.


When indenting, indent the statement after control
When indenting, indent the statement after control
Line 19: Line 24:
is a compound statement, indent ''both'' the curly braces and the
is a compound statement, indent ''both'' the curly braces and the
body of the statement (so that the body gets indented by ''two''
body of the statement (so that the body gets indented by ''two''
indents). This format is known as "GNU style" and is an option for
indents).
some code formatting tools.  Example indenting:


<pre>
Example:
 
<syntaxhighlight lang="cpp">
if (have_args)
if (have_args)
   {
   {
Line 30: Line 36:
else
else
   idx.push_back (make_value_list (args, arg_nm, tmp));
   idx.push_back (make_value_list (args, arg_nm, tmp));
</pre>
</syntaxhighlight>


If you have nested {{codeline|if}} statements, use extra braces for extra
If you have nested {{codeline|if}} statements, use extra braces for extra
clarification.
clarification.
==== Split long expressions ====


Split long expressions in such a way that a continuation line starts
Split long expressions in such a way that a continuation line starts
Line 40: Line 48:
innermost braces enclosing the split.  Example:
innermost braces enclosing the split.  Example:


<pre>
<syntaxhighlight lang="cpp">
SVD::type type = ((nargout == 0 || nargout == 1)
SVD::type type = ((nargout == 0 || nargout == 1)
                   ? SVD::sigma_only
                   ? SVD::sigma_only
                   : (nargin == 2) ? SVD::economy : SVD::std);
                   : (nargin == 2) ? SVD::economy : SVD::std);
</pre>
</syntaxhighlight>


=== Non indenting whitespace ===
==== Non-indenting whitespace ====


Consider putting extra braces around a multi-line expression to make it
Consider putting extra braces around a multi-line expression to make it
more readable, even if they are not necessary.  Also, do not hesitate to
more readable, even if they are not necessary.  Also, do not hesitate to
put extra braces anywhere if it improves clarity.
put extra braces anywhere if it improves clarity.
=== Pointer and Reference appearance ===
Declarations of pointers have the '*' character cuddled with the name of the variable.
<syntaxhighlight lang="cpp">
unsigned int *pointer_variable;
</syntaxhighlight>
However, references have the '&' character cuddled with the type of the variable.
<syntaxhighlight lang="cpp">
unsigned int& reference_variable;
</syntaxhighlight>
=== Miscellaneous ===


The negation operator is written with a space between the operator
The negation operator is written with a space between the operator
and its target, e.g., {{codeline|! A}}.
and its target, e.g., {{codeline|! A}}.
=== Line Length ===
Keep the length of source lines to 79 characters or less, for maximum
readability in the widest range of environments.  This is inherited from
the [https://www.gnu.org/prep/standards/standards.html#Formatting GNU Coding Standards].


=== Function headers ===
=== Function headers ===
Line 65: Line 83:
Format function headers like this:
Format function headers like this:


<pre>
<syntaxhighlight lang="cpp">
static bool
static bool
matches_patterns (const string_vector& patterns, int pat_idx,
matches_patterns (const string_vector& patterns, int pat_idx,
                   int num_pat, const std::string& name)
                   int num_pat, const std::string& name)
</pre>
</syntaxhighlight>


The return type of the function and any modifiers are specified on the first
The return type of the function and any modifiers are specified on the first
Line 76: Line 94:
parenthesis.  You should put a space before the left open parenthesis and after
parenthesis.  You should put a space before the left open parenthesis and after
commas, for both function definitions and function calls.
commas, for both function definitions and function calls.
=== Class declarations ===
The access specifier ({{codeline|public}}, {{codeline|protected}}, {{codeline|private}}) should always be stated rather than relying on the C++ language defaults for a particular object (for example, "{{codeline|class}}" = "{{codeline|private}}").
Within a class, the different access blocks should appear in the order 1) {{codeline|public}}, 2) {{codeline|protected}}, 3) {{codeline|private}}.
Within an access block, member functions should be specified before member variables.  If there are both member functions and member variables use
    //--------
between the sections to visually separate the two categories.


=== Namespace ===
=== Namespace ===
Line 90: Line 120:
* Do not declare anything on the std namespace;
* Do not declare anything on the std namespace;


{{Code|namespace style on a .h file|<pre>
{{Code|namespace style on a .h file|<syntaxhighlight lang="cpp">
// Note indentation
// Note indentation
namespace octave
namespace octave
Line 103: Line 133:
   }
   }
}
}
</pre>}}
</syntaxhighlight>}}


{{Code|namespace style on a .cc file|<pre>
{{Code|namespace style on a .cc file|<syntaxhighlight lang="cpp">
// Note indentation and that functions are not defined
// Note indentation and that functions are not defined
// as "octave::math::foo:foo"
// as "octave::math::foo:foo"
Line 118: Line 148:
   }
   }
}
}
</pre>}}
</syntaxhighlight>}}


== Naming ==
== Naming ==
Line 125: Line 155:
names consisting of 1-2 letters.  Do not use mixed case names.
names consisting of 1-2 letters.  Do not use mixed case names.


=== Member Variables ===
Member variables should use the prefix "m_" whenever possible.
=== Class Variables ===
Class variables should use the prefix "s_" (for "static") whenever possible.
=== Filenames ===
As with m-files, the file name of a C++ source file containing a class should match the name of the class defined within the file.  For example, "password.h" defines the class "password" rather than "passwd.h" which is a common abbreviation for "password".


== Header Files ==
== Header Files ==
Line 162: Line 203:
== C++ features ==
== C++ features ==


=== C++11 features ===
=== references ===
 
Use references when passing variables that will be changed by a subroutine rather than the C-style method of passing pointers.
 
{| class="wikitable"
! style="color:green;" | good
! style="color:darkred;" | bad
|-
| <syntaxhighlight lang="c++">
void foo (int& a_ref)
{
  // foo changes content of `a_ref`
  a_ref = a_ref + 1;
}
 
void bar ()
{
  int a = 42;
  foo (a);
}
</syntaxhighlight>
| <syntaxhighlight lang="c++">
void foo (int *a_ptr)
{
  // foo changes content of `a_ptr`
  *a_ptr = *aptr + 1;
}
 
void bar ()
{
  int a = 42;
  foo (&a);
}
</syntaxhighlight>
|}
 
When passing variables that are large, but will not be changed in a subroutine (read-only), consider using 'const' references.  This helps avoid overflowing the finite stack capacity of a program while still ensuring that read-only access is enforced.
 
{| class="wikitable"
! style="color:green;" | good
! style="color:darkred;" | bad
|-
| <syntaxhighlight lang="c++">
void foo (const std::string& str_ref)
{
  // foo does not change content of `str_ref`
}
 
void bar ()
{
  std::string str ("This is a large variable, however as a reference it will take up just 8 bytes on the stack when passed to the subroutine foo()");
  foo (str);
}
</syntaxhighlight>
| <syntaxhighlight lang="c++">
void foo (std::string str_copy)
{
  // foo does not change content of `str_copy`
}


C++11 features are generally allowed. Check if the feature you want to
void bar ()
use has been already used.  If not, ask on the mailing list.
{
  std::string str ("This is a large variable that will be copied on to the stack and passed as a temporary variable to the subroutine foo()");
  foo (str);
}
</syntaxhighlight>
|}


=== std::string ===
=== std::string ===


When an empty string is required, use @qcode{""}, rather than creating an empty
When an empty string is required, use <code>""</code>, rather than creating an empty
string object with @code{std::string ()}.
string object with <code>std::string ()</code>.


=== auto ===
=== auto ===
Line 181: Line 285:
* Beware of copy when using {{codeline|auto}} in for loops. Pass by reference and use {{codeline|const}} unless you're dealing with simple types such as {{codeline|int}}. See [http://lists.gnu.org/archive/html/octave-maintainers/2016-06/msg00144.html 'auto' uses and for-range loops] on the maintainers mailing list for more details.
* Beware of copy when using {{codeline|auto}} in for loops. Pass by reference and use {{codeline|const}} unless you're dealing with simple types such as {{codeline|int}}. See [http://lists.gnu.org/archive/html/octave-maintainers/2016-06/msg00144.html 'auto' uses and for-range loops] on the maintainers mailing list for more details.


=== C++14 ===
=== C++ style casting ===
 
Always use one of the four C++ long style casting forms ({{codeline|static_cast}}, {{codeline|dynamic_cast}}, {{codeline|reinterpret_cast}}, {{codeline|const_cast}}) rather than C-style forms (type cast {{codeline|(new_type) variable}} or the function form {{codeline|new_type (variable)}}).
 
=== C++11 features ===
 
A C++11 compatible compiler is required for [[Building | building Octave]].  Please make use of all C++11 features.
 
=== C++14, C++17, C++20 features ===


Do not use C++14 features.  Octave is widely used in very old systems and we
Try to avoid C++14, C++17, or C++20 features.  Octave is widely used in very old systems and we want them to be able to use up to date versions of Octave.  Building a recent compiler in such systems is not a trivial task so the limitation must happen
want them to be able to use up to date versions of Octave.  Building a recent
compiler in such systems is not a trivial task so the limitation must happen
in Octave.
in Octave.


An exception: code that requires C++14 feature must also implement an
If the implementation using a C++14, C++17, or C++20 feature is very beneficial, make it optional via <code>configure</code> feature detection or also implement an alternative code in the absence of said feature.  In any case, please get in contact with the Octave maintainers on [https://octave.discourse.group/c/maintainers/7 Discourse].
alternative code in the absence of said feature.  In such case, use a
 
configure checkThis increases maintenance a lot, must be used sparsely,
<syntaxhighlight lang="cpp">
and requires approval from other maintainers.
#if defined (HAVE_THIS_C14_FEATURE)
  // code that really needs it
#else
  // alternative code in its absence
#endif
</syntaxhighlight>
 
== Doxygen ==
 
Doxygen documentation can be a great help when developing octave however the current state has a lot of room for improvement. For more information about Doxygen in Octave look at [[Doxygen]].
 
=== Doxygen Style Guide ===
 
Doxygen allows for a variety of commenting styles. In order to maintain uniformity across the entire project the following rules should be applied:
 
* For Doxygen comments use only {{codeline|//!}} and NOT {{codeline|/*! ... */}}, regardless of the size of the block comment
* Use {{codeline|@}} for any [https://www.stack.nl/~dimitri/doxygen/manual/commands.html Doxygen Special Commands]
* Use as little formatting as possibleRestrict to [https://www.stack.nl/~dimitri/doxygen/manual/markdown.html Markdown] and avoid HTML-markup.
* Do NOT use the {{codeline|@brief}} command, the first sentence will automatically be used as the summary description.
* The first sentence should describe briefly what the function does and end with a period.
* Leave a blank line between the Doxygen comment and function definition.
 
An example of properly used Doxygen would look like:
 
<syntaxhighlight lang="cpp">
//! Does something interesting with its arguments.
//!
//! Long comment with **bold** special commands.
//!
//! @param some_param Really should figure out what to do.
//! @param another_param Does something cool with @p some_param.
//!
//! And some example using syntax highlighting:
//!
//! @code{.cc}
//! double v = 1.0;
//! int n = 2;
//! some_function (v, n);
//! @endcode


#if defined (HAVE_THIS_C14_FEATURE)
void
  // code that really needs it
some_function (double some_param, int another_param)
#else
{
  // alternative code in its absence
  // ...
#endif
}
</syntaxhighlight>


== Comments ==
== Comments ==
Line 205: Line 354:
The preferred comment mark for places that may need further attention is
The preferred comment mark for places that may need further attention is
with {{codeline|FIXME:}} comments.
with {{codeline|FIXME:}} comments.
[[Category:Development]]
1,072

edits

Navigation menu