C++ style guide: Difference between revisions
no edit summary
Carandraug (talk | contribs) (→Formatting: add section about namespace) |
No edit summary |
||
(12 intermediate revisions by 6 users not shown) | |||
Line 14: | Line 14: | ||
We use spaces for indentation. Absolutely do not use tabs in your code. | We use spaces for indentation. Absolutely do not use tabs in your code. | ||
You should probably set your editor to emit spaces when you hit the tab key. | You should probably set your editor to emit spaces when you hit the tab key. | ||
When indenting, indent the statement after control | |||
structures (like {{codeline|if}}, {{codeline|while}}, etc.). If there | |||
is a compound statement, indent ''both'' the curly braces and the | |||
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 | |||
some code formatting tools. Example indenting: | |||
<syntaxhighlight lang="cpp"> | |||
if (have_args) | |||
{ | |||
idx.push_back (first_args); | |||
have_args = false; | |||
} | |||
else | |||
idx.push_back (make_value_list (args, arg_nm, tmp)); | |||
</syntaxhighlight> | |||
If you have nested {{codeline|if}} statements, use extra braces for extra | |||
clarification. | |||
Split long expressions in such a way that a continuation line starts | |||
with an operator rather than identifier. If the split occurs inside | |||
braces, continuation should be aligned with the first char after the | |||
innermost braces enclosing the split. Example: | |||
<syntaxhighlight lang="cpp"> | |||
SVD::type type = ((nargout == 0 || nargout == 1) | |||
? SVD::sigma_only | |||
: (nargin == 2) ? SVD::economy : SVD::std); | |||
</syntaxhighlight> | |||
=== Non indenting whitespace === | |||
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 | |||
put extra braces anywhere if it improves clarity. | |||
The negation operator is written with a space between the operator | |||
and its target, e.g., {{codeline|! A}}. | |||
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> | |||
=== Line Length === | === Line Length === | ||
Line 20: | Line 72: | ||
readability in the widest range of environments. This is inherited from | readability in the widest range of environments. This is inherited from | ||
the [https://www.gnu.org/prep/standards/standards.html#Formatting GNU Coding Standards]. | the [https://www.gnu.org/prep/standards/standards.html#Formatting GNU Coding Standards]. | ||
=== Function headers === | |||
Format function headers like this: | |||
<syntaxhighlight lang="cpp"> | |||
static bool | |||
matches_patterns (const string_vector& patterns, int pat_idx, | |||
int num_pat, const std::string& name) | |||
</syntaxhighlight> | |||
The return type of the function and any modifiers are specified on the first | |||
line. The function name on the second line should start in column 1, and | |||
multi-line argument lists should be aligned on the first char after the open | |||
parenthesis. You should put a space before the left open parenthesis and after | |||
commas, for both function definitions and function calls. | |||
=== Namespace === | === Namespace === | ||
All code should be in the octave namespace | All code should be in the octave namespace. This is an ongoing project. We | ||
are still moving existing classes into namespaces but all new classes | are still moving existing classes into namespaces but all new classes | ||
should go somewhere into octave | should go somewhere into the "octave" namespace. There is 1 extra level for namespaces | ||
inside octave to be used with care, we don't want too many namespaces. | inside octave to be used with care, we don't want too many namespaces. | ||
Ask before creating a new namespace. | Ask before creating a new namespace. | ||
* | * Indent namespaces as any other block. Emacs and other editors can do this automatically. | ||
* Define namespace on the .cc files; | * Define namespace on the .cc files; | ||
* Do not use "using X" directives; | * Do not use "using X" directives; | ||
* Do not declare anything on the std namespace; | * Do not declare anything on the std namespace; | ||
{{Code|namespace style on a .h file|< | {{Code|namespace style on a .h file|<syntaxhighlight lang="cpp"> | ||
// Note | // Note indentation | ||
namespace octave | namespace octave | ||
{ | { | ||
namespace math | namespace math | ||
{ | { | ||
class foo | |||
class foo | { | ||
{ | public: | ||
public: | foo (...); | ||
}; | |||
} | |||
}; | |||
} | |||
} | } | ||
</ | </syntaxhighlight>}} | ||
{{Code|namespace style on a .cc file|< | {{Code|namespace style on a .cc file|<syntaxhighlight lang="cpp"> | ||
// Note | // Note indentation and that functions are not defined | ||
// as "octave::math::foo:foo" | // as "octave::math::foo:foo" | ||
namespace octave | namespace octave | ||
{ | { | ||
namespace math | namespace math | ||
{ | { | ||
foo::foo (...) | |||
{ | |||
...; | |||
} | |||
} | |||
} | |||
</syntaxhighlight>}} | |||
== Naming == | |||
Use lowercase names if possible. Uppercase is acceptable for variable | |||
names consisting of 1-2 letters. Do not use mixed case names. | |||
== Header Files == | == Header Files == | ||
Line 75: | Line 142: | ||
=== Order of Includes === | === Order of Includes === | ||
In source files (not headers files), use the following order with an empty line between each section: | |||
# config.h | # config.h | ||
# The C++ wrappers for C headers (cstdlib, cassert, etc.) | # The C++ wrappers for C headers (cstdlib, cassert, etc.) | ||
# C++ standard library headers (iostream, list, map, etc.) | # C++ standard library headers (iostream, list, map, etc.) | ||
# Other library header files (glpk.h, curl.h, etc., should be protected by {{codeline|#if defined (HAVE_FOO_H)}} since they may be missing on the build system) | # Other library header files (glpk.h, curl.h, etc., should be protected by {{codeline|#if defined (HAVE_FOO_H)}} since they may be missing on the build system) | ||
# Octave's liboctave headers | # Octave's liboctave headers | ||
# Octave's libinterp headers | # Octave's libinterp headers | ||
# Octave's libgui headers | |||
Other POSIX headers (sys/types.h, unistd.h, etc., should not be included directly into Octave sources. For portability, use a wrapper function. Anything you need is probably already available as a wrapper around a function or header provided by gnulib. See the files in liboctave/wrappers. This is necessary because although gnulib is great for portability, it does not generally work well with C++. | |||
Similarly, Windows headers should not be included directly into Octave sources. Wrappers that provide the needed functionality in an OS-independent way should be used instead. This is almost always possible and there are many examples in the Octave sources. | |||
Each grouping of header files should be alphabetized unless there is some | Each grouping of header files should be alphabetized unless there is some | ||
Line 89: | Line 160: | ||
{{Path|oct-parse.in.yy}} and there is a comment in the file for that one. | {{Path|oct-parse.in.yy}} and there is a comment in the file for that one. | ||
There is a strict ordering of header files/libraries that must be followed. There are '''no exceptions''' to these rules: | |||
=== C++11 === | * The functions in liboctave/wrappers may only use headers and symbols from gnulib, standard libraries, or OS-dependent libraries. They '''must not''' use any headers or symbols from other parts of liboctave, libinterp, or libgui. | ||
* liboctave '''must not''' use any headers or symbols from libinterp or libgui. It must be fully functional without the interpreter or GUI. | |||
* libinterp '''must not''' use any headers or symbols from libgui. It must be fully functional without the GUI. | |||
As much as possible, header files should be independent of other header files. | |||
Header files '''must not''' include config.h. Instead, they should begin by including octave-config.h. | |||
Header files should not use any "#if defined (HAVE_FEATURE)" conditionals. This is not quite true yet, but we are almost there. '''No new conditionals may be added.''' | |||
== C++ features == | |||
=== C++11 features === | |||
C++11 features are generally allowed. Check if the feature you want to | C++11 features are generally allowed. Check if the feature you want to | ||
use has been already used. If not, ask on the mailing list. | use has been already used. If not, ask on the mailing list. | ||
==== auto | === std::string === | ||
When an empty string is required, use @qcode{""}, rather than creating an empty | |||
string object with @code{std::string ()}. | |||
=== auto === | |||
Use of {{codeline|auto}} is allowed only where it helps readability | Use of {{codeline|auto}} is allowed only where it helps readability | ||
Line 117: | Line 205: | ||
and requires approval from other maintainers. | and requires approval from other maintainers. | ||
<syntaxhighlight lang="cpp"> | |||
#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 possible. Restrict 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 | |||
void | |||
some_function (double some_param, int another_param) | |||
{ | |||
// ... | |||
} | |||
</syntaxhighlight> | |||
== Comments == | |||
=== FIXME notes === | |||
The preferred comment mark for places that may need further attention is | |||
with {{codeline|FIXME:}} comments. |