WPILib C++ Style Guide (Based on the Google C++ Style Guide)
- - -Background
- -This guide is a work in progress. -We are currently working on getting this guide updated to -a point where it is useful for WPILib developers to use.
- -C++ is one of the two main languages (Java being the other) -used in WPILib; in order to maintain consistency and keep the -maintenance of the code manageable, we use this style guide.
- -There are two main overarching purposes to this guide. The first -is to act as a normal C++ style guide (both in terms fo formatting -and programming practices) for C++ developers of WPILib. -The other purpose is to help Java programmers who may -know a moderate amount of C++ but may not be fully -up to date with things like C++11 and so may not even -realize that certain C++ features exist.
- -This style guide is a heavily modified version of the - -Google C++ Style Guide. The Google Style Guide has -a lot of good points and is a good read, but in order -to cut the style guide down to a more readable size and to -focus mroe on WPILib-specific information, we have -altetered the original style guide in several ways.
- -One way in which we haven't done much to -alter the original style guide is to keep the vast -majority of the formatting/naming/etc. related -information intact. This is both so that we -do not have to write up our own standards and so -that existing tools such as clang-format and -the Google eclipse format configuration files -can work out of the box. All of these things -should be relatively non-controversial and do not -require much discussion.
- -Where we deviate more from the original guide is -in the style of the code itself. At the moment (ie, -when we first created this modified version), we -deleted all of the sections of the original guide -which mandate particular programming practices -such as forbidding exceptions, multiple inheritance, -etc. However, as time goes on, we gradually add in more -information along this lines, either by copying -directly from Google's Style Guide or by writing -our own decisions and best practices, some of which -may be very WPILib-specific.
- -As the original guide makes very clear, consistency -is extremely important to keeping the code base -manageable, and so we encourage that, wherever -reasonable, that you keep everything consistent -with whatever the standard style is.
- -Along with just C++ style, it is also important -to keep in mind that WPILib consists of both a C++ -and Java half. In order to keep things consistent -and easier for users, we ask that, in general, -Java and C++ be kept as consistent with one another -as reasonable. This includes everything from using -two spaces for indentation in both language to -keeping the inheritance structure essentially the -same in both. Although the two do not have to be -precisely the same, it does mean that if there is -something that you are doing which will be imposssible -to reproduce in some way in Java, then you may -want to reconsider.
- -One final thing to remember is that High School -students with relatively little experience programming -are the main user for this code, and throwing the full -brunt of C++ at a student just learning how to program -is likely not the best of ideas. As such, any -user-facing APIs should minimize the use of any -more complicated C++ features. As always, -use your judgement and ask others in cases where -there is something which may violate anything -in this guide.
- -Programming Guidelines
-C++ is a large, complicated language, and in order -to ensure that we stay consistent and maintain certain -best practices, we have certain rules. For the most part -these are common sense rules and in some cases exist -solely to point out features of C++ that someone more -familiar with Java may not realize even exist.
- -Pointers
-In general, we strongly discourage the use of -raw pointers in C++ code; instead, references or -STL pointers should be used where appropriate. -There are two exceptions to this rule:
--
-
- When interfacing with lower-level C code or - with any libraries which force you to use raw pointers. -
- In order to keep user interfaces consistent,
- we may keep around deprecated functions which
- take raw pointers. Any user-facing functions
- which take raw pointers should be deprecated
- using the
-
[[deprecated]]- attribute and replaced with either references - or STL pointers.
-
As of C++11, the following are options in the -place of raw pointers:
--
-
std::unique_ptrShould be used - when you still need to use a pointer, but you - only need one entity to own the pointer. The -std::unique_ptrwill automatically - be deleted when there are no more references to - it.
- std::shared_ptrShould be used - when you still need to use a pointer and you - need many references to the object. When - there are zero remaining references to the - object, it will be deleted. Usestd::weak_ptr- where necessary to avoid circular dependencies - or other potential issues.
- - L-value references (the traditional sort - of reference that has been around since before C++11) - should be used when you want to pass around a - reference to an object and want to guarantee - that it won't be null. Use const references - if you want to avoid copying a large object - but don't want to modify it. -
- R-value references were introduced in C++11
- and allow for the use of
std::move. - R-value references should be used where it makes - sense that a parameter to a function is having - its ownership passed from one place to another. - In general, R-value references are not inherently - bad, but they do introduce additional complexity - that may confuse people who are not familiar - with them.
-
Deprecation
-When updating APIs, make liberal use of the
-[[deprecated]] attribute (although if
-it is reasonable to simply remove any old interfaces
-then do so) to indicate that users should no longer
-use the function. Currently, this will cause warnings
-in user code and errors in the WPILib build.
-[[deprecated("This is a deprecated function; this text will be displayed when"
- " the compiler throws a warning.")]]
-void foo() {}
-class [[deprecated("This is a deprecated class.")]] Foo {};
-int bar [[deprecated("This is a deprecated variable.")]];
-
-
-See -here for more information on deprecation.
- -Header Files
- -In general, every .cc file should have an
-associated .h file. There are some common
-exceptions, such as unittests and
-small .cpp files containing just a
-main() function.
Correct use of header files can make a huge difference to -the readability, size and performance of your code.
- -The following rules will guide you through the various -pitfalls of using header files.
- - -Self-contained Headers
- -Header files should be self-contained and end in .h. Files that
-are meant for textual inclusion, but are not headers, should end in
-.inc. Separate -inl.h headers are disallowed.
All header files should be self-contained. In other -words, users and refactoring tools should not have to adhere to special -conditions in order to include the header. Specifically, a -header should have #pragma once, -should include all other headers it needs, and should not require any -particular symbols to be defined.
- -There are rare cases where a file is not meant to be self-contained, but
-instead is meant to be textually included at a specific point in the code.
-Examples are files that need to be included multiple times or
-platform-specific extensions that essentially are part of other headers. Such
-files should use the file extension .inc.
If a template or inline function is declared in a .h file,
-define it in that same file. The definitions of these constructs must
-be included into every .cc file that uses them, or the
-program may fail to link in some build configurations. Do not move these
-definitions to separate -inl.h files.
As an exception, a function template that is explicitly
-instantiated for all relevant sets of template arguments, or
-that is a private member of a class, may
-be defined in the only .cc file that
-instantiates the template.
#pragma once
- -All header files should have #pragma once at the top to
-prevent multiple inclusion.
-
Forward Declarations
- -You may forward declare ordinary classes in order to avoid
-unnecessary #includes.
A "forward declaration" is a declaration of a class,
-function, or template without an associated definition.
-#include lines can often be replaced with
-forward declarations of whatever symbols are actually
-used by the client code.
-
-
- Unnecessary
#includes force the - compiler to open more files and process more - input.
-
- - They can also force your code to be recompiled more - often, due to changes in the header. -
-
-
- It can be difficult to determine the correct form - of a forward declaration in the presence of features - like templates, typedefs, default parameters, and using - declarations. - -
- It can be difficult to determine whether a forward
- declaration or a full
#includeis needed - for a given piece of code, particularly when implicit - conversion operations are involved. In extreme cases, - replacing an#includewith a forward - declaration can silently change the meaning of - code.
-
- - Forward declaring multiple symbols from a header
- can be more verbose than simply
-
#includeing the header.
-
- - Forward declarations of functions and templates can - prevent the header owners from making - otherwise-compatible changes to their APIs; for - example, widening a parameter type, or adding a - template parameter with a default value. -
- Forward declaring symbols from namespace
-
std::usually yields undefined - behavior.
-
- - Structuring code to enable forward declarations - (e.g. using pointer members instead of object members) - can make the code slower and more complex. - -
- The practical efficiency benefits of forward - declarations are unproven. -
-
-
- When using a function declared in a header file,
- always
#includethat header.
-
- - When using a class template, prefer to
-
#includeits header file.
-
- - When using an ordinary class, relying on a forward
- declaration is OK, but be wary of situations where a
- forward declaration may be insufficient or incorrect;
- when in doubt, just
#includethe - appropriate header.
-
- - Do not replace data members with pointers just to
- avoid an
#include.
-
Please see Names and Order -of Includes for rules about when to #include a header.
-Inline Functions
- -Define functions inline only when they are small, say, 10 -lines or less.
-You can declare functions in a way that allows the compiler to expand -them inline rather than calling them through the usual -function call mechanism.
-Inlining a function can generate more efficient object -code, as long as the inlined function is small. Feel free -to inline accessors and mutators, and other short, -performance-critical functions.
-Overuse of inlining can actually make programs slower. -Depending on a function's size, inlining it can cause the -code size to increase or decrease. Inlining a very small -accessor function will usually decrease code size while -inlining a very large function can dramatically increase -code size. On modern processors smaller code usually runs -faster due to better use of the instruction cache.
-A decent rule of thumb is to not inline a function if -it is more than 10 lines long. Beware of destructors, -which are often longer than they appear because of -implicit member- and base-destructor calls!
- -Another useful rule of thumb: it's typically not cost -effective to inline functions with loops or switch -statements (unless, in the common case, the loop or -switch statement is never executed).
- -It is important to know that functions are not always -inlined even if they are declared as such; for example, -virtual and recursive functions are not normally inlined. -Usually recursive functions should not be inline. The -main reason for making a virtual function inline is to -place its definition in the class, either for convenience -or to document its behavior, e.g., for accessors and -mutators.
-Function Parameter Ordering
- -When defining a function, parameter order is: inputs, then -outputs.
-Parameters to C/C++ functions are either input to the
-function, output from the function, or both. Input
-parameters are usually values or const
-references, while output and input/output parameters will
-be non-const pointers. When ordering
-function parameters, put all input-only parameters before
-any output parameters. In particular, do not add new
-parameters to the end of the function just because they
-are new; place new input-only parameters before the
-output parameters.
This is not a hard-and-fast rule. Parameters that are -both input and output (often classes/structs) muddy the -waters, and, as always, consistency with related -functions may require you to bend the rule.
- -Names and Order of Includes
- -Use standard order for readability and to avoid hidden
-dependencies: Related header, C library, C++ library, other libraries'
-.h, your project's .h.
-All of a project's header files should be
-listed as descendants of the project's source
-directory without use of UNIX directory shortcuts
-. (the current directory) or ..
-(the parent directory). For example,
-
-google-awesome-project/src/base/logging.h
-should be included as:
#include "base/logging.h" -- -
In dir/foo.cc or
-dir/foo_test.cc, whose main
-purpose is to implement or test the stuff in
-dir2/foo2.h, order your includes
-as follows:
-
-
dir2/foo2.h.
-
- - C system files. - -
- C++ system files. - -
- Other libraries'
.h- files.
-
- -
- Your project's
.h- files.
-
C and C++ standard library includes are considered system files in their -respective group. Includes within one group should not have an empty line -separating them, while there should be an empty line between groups.
- -With the preferred ordering, if
-dir2/foo2.h omits any necessary
-includes, the build of dir/foo.cc
-or dir/foo_test.cc will break.
-Thus, this rule ensures that build breaks show up first
-for the people working on these files, not for innocent
-people in other packages.
dir/foo.cc and
-dir2/foo2.h are usually in the same
-directory (e.g. base/basictypes_test.cc and
-base/basictypes.h), but may sometimes be in different
-directories too.
Within each section the includes should be ordered -alphabetically. Note that older code might not conform to -this rule and should be fixed when convenient.
- -You should include all the headers that define the symbols you rely
-upon (except in cases of forward
-declaration). If you rely on symbols from bar.h,
-don't count on the fact that you included foo.h which
-(currently) includes bar.h: include bar.h
-yourself, unless foo.h explicitly demonstrates its intent
-to provide you the symbols of bar.h. However, any
-includes present in the related header do not need to be included
-again in the related cc (i.e., foo.cc can
-rely on foo.h's includes).
For example, the includes in
-
-google-awesome-project/src/foo/internal/fooserver.cc
-might look like this:
#include "foo/server/fooserver.h" - -#include <sys/types.h> -#include <unistd.h> - -#include <hash_map> -#include <vector> - -#include "base/basictypes.h" -#include "base/commandlineflags.h" -#include "foo/server/bar.h" -- -
Sometimes, system-specific code needs -conditional includes. Such code can put conditional -includes after other includes. Of course, keep your -system-specific code small and localized. Example:
- -#include "foo/public/fooserver.h" - -#include "base/port.h" // For LANG_CXX11. - -#ifdef LANG_CXX11 -#include <initializer_list> -#endif // LANG_CXX11 -- -
Naming
- -The most important consistency rules are those that govern -naming. The style of a name immediately informs us what sort of -thing the named entity is: a type, a variable, a function, a -constant, a macro, etc., without requiring us to search for the -declaration of that entity. The pattern-matching engine in our -brains relies a great deal on these naming rules. -
- -Naming rules are pretty arbitrary, but - we feel that -consistency is more important than individual preferences in this -area, so regardless of whether you find them sensible or not, -the rules are the rules.
- -General Naming Rules
- -Function names, variable names, and filenames should be -descriptive; eschew abbreviation.
-Give as descriptive a name as possible, within reason. -Do not worry about saving horizontal space as it is far -more important to make your code immediately -understandable by a new reader. Do not use abbreviations -that are ambiguous or unfamiliar to readers outside your -project, and do not abbreviate by deleting letters within -a word.
- -int price_count_reader; // No abbreviation. -int num_errors; // "num" is a widespread convention. -int num_dns_connections; // Most people know what "DNS" stands for. -- -
int n; // Meaningless. -int nerr; // Ambiguous abbreviation. -int n_comp_conns; // Ambiguous abbreviation. -int wgc_connections; // Only your group knows what this stands for. -int pc_reader; // Lots of things can be abbreviated "pc". -int cstmr_id; // Deletes internal letters. -- -
File Names
- -Filenames should be all lowercase and can include
-underscores (_) or dashes (-).
-Follow the convention that your
-
-project uses. If there is no consistent
-local pattern to follow, prefer "_".
Examples of acceptable file names:
- --
-
my_useful_class.cc
- my-useful-class.cc
- myusefulclass.cc
- myusefulclass_test.cc // _unittest and _regtest are deprecated.
-
C++ files should end in .cc and header files should end in
-.h. Files that rely on being textually included at specific points
-should end in .inc (see also the section on
-self-contained headers).
Do not use filenames that already exist in
-/usr/include, such as db.h.
In general, make your filenames very specific. For
-example, use http_server_logs.h rather than
-logs.h. A very common case is to have a pair
-of files called, e.g., foo_bar.h and
-foo_bar.cc, defining a class called
-FooBar.
Inline functions must be in a .h file. If
-your inline functions are very short, they should go
-directly into your .h file.
Type Names
- -Type names start with a capital letter and have a capital
-letter for each new word, with no underscores:
-MyExcitingClass, MyExcitingEnum.
The names of all types — classes, structs, typedefs, -and enums — have the same naming convention. Type names -should start with a capital letter and have a capital letter -for each new word. No underscores. For example:
- -// classes and structs
-class UrlTable { ...
-class UrlTableTester { ...
-struct UrlTableProperties { ...
-
-// typedefs
-typedef hash_map<UrlTableProperties *, string> PropertiesMap;
-
-// enums
-enum UrlTableErrors { ...
-
-
-Variable Names
- -The names of variables and data members are all lowercase, with
-underscores between words. Data members of classes (but not structs)
-additionally are prefixed with "m_". For instance:
-a_local_variable, a_struct_data_member,
-m_a_class_data_member.
Common Variable names
- -For example:
- -string table_name; // OK - uses underscore. -string tablename; // OK - all lowercase. -- -
string tableName; // Bad - mixed case. -- -
Class Data Members
- -Data members of classes, both static and non-static, are -named like ordinary nonmember variables, but prefixed with a -"m_".
- -class TableInfo {
- ...
- private:
- string m_table_name; // OK - m_ at beginning.
- string m_tablename; // OK.
- static Pool<TableInfo>* m_pool; // OK.
-};
-
-
-Struct Data Members
- -Data members of structs, both static and non-static, -are named like ordinary nonmember variables. They do not have -the preceding "m_" that data members in classes have.
- -struct UrlTableProperties {
- string name;
- int num_entries;
- static Pool<UrlTableProperties>* pool;
-};
-
-
-
-See Structs vs. -Classes for a discussion of when to use a struct -versus a class.
- -Global Variables
- -There are no special requirements for global
-variables, which should be rare in any case, but if you
-use one, consider prefixing it with g_ or
-some other marker to easily distinguish it from local
-variables.
Constant Names
- -Use a k followed by mixed case, e.g.,
-kDaysInAWeek, for constants defined globally or within a class.
As a convenience to the reader, compile-time constants of global or class scope
-follow a different naming convention from other variables.
-Use a k followed by words with uppercase first letters:
const int kDaysInAWeek = 7; -- -
This convention may optionally be used for compile-time constants of local scope; -otherwise the usual variable naming rules apply. - -
Function Names
- -Regular functions have mixed case; accessors and mutators
-match the name of the variable:
-MyExcitingFunction(),
-MyExcitingMethod(),
-my_exciting_member_variable(),
-set_my_exciting_member_variable().
Regular Functions
- -Functions should start with a capital letter and have -a capital letter for each new word. No underscores.
- -If your function crashes upon an error, you should -append OrDie to the function name. This only applies to -functions which could be used by production code and to -errors that are reasonably likely to occur during normal -operation.
- -AddTableEntry() -DeleteUrl() -OpenFileOrDie() -- -
Accessors and Mutators
- -Accessors and mutators (get and set functions) should
-match the name of the variable they are getting and
-setting. This shows an excerpt of a class whose instance
-variable is num_entries_.
class MyClass {
- public:
- ...
- int num_entries() const { return num_entries_; }
- void set_num_entries(int num_entries) { num_entries_ = num_entries; }
-
- private:
- int num_entries_;
-};
-
-
-You may also use lowercase letters for other very -short inlined functions. For example if a function were -so cheap you would not cache the value if you were -calling it in a loop, then lowercase naming would be -acceptable.
- -Namespace Names
- -Namespace names are all lower-case,
-and based on project names and possibly their directory
-structure: google_awesome_project.
See Namespaces for a -discussion of namespaces and how to name them.
- -Enumerator Names
- -Enumerators should be named like
-constants: kEnumName.
The enumeration name,
-UrlTableErrors (and
-AlternateUrlTableErrors), is a type, and
-therefore mixed case.
enum UrlTableErrors {
- kOK = 0,
- kErrorOutOfMemory,
- kErrorMalformedInput,
-};
-
-
-Macro Names
- -You're not really going to
-define a macro, are you? If you do, they're like this:
-MY_MACRO_THAT_SCARES_SMALL_CHILDREN.
Please see the description -of macros; in general macros should not be used. -However, if they are absolutely needed, then they should be -named with all capitals and underscores.
- -#define ROUND(x) ... -#define PI_ROUNDED 3.0 -- -
Exceptions to Naming Rules
- -If you are naming something that is analogous to an -existing C or C++ entity then you can follow the existing -naming convention scheme.
--
-
bigopen()
- - function name, follows form of
open()
-
- uint
- typedef
-
- bigpos
- structorclass, follows - form ofpos
-
- sparse_hash_map
- - STL-like entity; follows STL naming conventions - -
LONGLONG_MAX
- - a constant, as in
INT_MAX
-
Comments
- -Though a pain to write, comments are absolutely vital to -keeping our code readable. The following rules describe what -you should comment and where. But remember: while comments are -very important, the best code is self-documenting. Giving -sensible names to types and variables is much better than using -obscure names that you must then explain through comments.
- -When writing your comments, write for your audience: the -next -contributor who will need to -understand your code. Be generous — the next -one may be you!
- -Comment Style
- -Use either the // or /* */
-syntax, as long as you are consistent.
You can use either the // or the /*
-*/ syntax; however, // is
-much more common. Be consistent with how you
-comment and what style you use where.
File Comments
- -Start each file with license -boilerplate, followed by a description of its -contents.
-Legal Notice and Author -Line
- - - -Every file should contain license -boilerplate. Choose the appropriate boilerplate for the -license used by the project (for example, Apache 2.0, -BSD, LGPL, GPL).
- -If you make significant changes to a file with an -author line, consider deleting the author line.
- -File Contents
- -Every file should have a comment at the top describing -its contents.
- -Generally a .h file will describe the
-classes that are declared in the file with an overview of
-what they are for and how they are used. A
-.cc file should contain more information
-about implementation details or discussions of tricky
-algorithms. If you feel the implementation details or a
-discussion of the algorithms would be useful for someone
-reading the .h, feel free to put it there
-instead, but mention in the .cc that the
-documentation is in the .h file.
Do not duplicate comments in both the .h
-and the .cc. Duplicated comments
-diverge.
Class Comments
- -Every class definition should have an accompanying comment -that describes what it is for and how it should be used.
-// Iterates over the contents of a GargantuanTable. Sample usage:
-// GargantuanTableIterator* iter = table->NewIterator();
-// for (iter->Seek("foo"); !iter->done(); iter->Next()) {
-// process(iter->key(), iter->value());
-// }
-// delete iter;
-class GargantuanTableIterator {
- ...
-};
-
-
-If you have already described a class in detail in the -comments at the top of your file feel free to simply -state "See comment at top of file for a complete -description", but be sure to have some sort of -comment.
- -Document the synchronization assumptions the class -makes, if any. If an instance of the class can be -accessed by multiple threads, take extra care to document -the rules and invariants surrounding multithreaded -use.
- -Function Comments
- -Declaration comments describe use of the function; comments -at the definition of a function describe operation.
-Function Declarations
- -Every function declaration should have comments -immediately preceding it that describe what the function -does and how to use it. These comments should be -descriptive ("Opens the file") rather than imperative -("Open the file"); the comment describes the function, it -does not tell the function what to do. In general, these -comments do not describe how the function performs its -task. Instead, that should be left to comments in the -function definition.
- -Types of things to mention in comments at the function -declaration:
- --
-
- What the inputs and outputs are. - -
- For class member functions: whether the object - remembers reference arguments beyond the duration of - the method call, and whether it will free them or - not. - -
- If the function allocates memory that the caller - must free. - -
- Whether any of the arguments can be a null - pointer. - -
- If there are any performance implications of how a - function is used. - -
- If the function is re-entrant. What are its - synchronization assumptions? -
Here is an example:
- -// Returns an iterator for this table. It is the client's
-// responsibility to delete the iterator when it is done with it,
-// and it must not use the iterator once the GargantuanTable object
-// on which the iterator was created has been deleted.
-//
-// The iterator is initially positioned at the beginning of the table.
-//
-// This method is equivalent to:
-// Iterator* iter = table->NewIterator();
-// iter->Seek("");
-// return iter;
-// If you are going to immediately seek to another place in the
-// returned iterator, it will be faster to use NewIterator()
-// and avoid the extra seek.
-Iterator* GetIterator() const;
-
-
-However, do not be unnecessarily verbose or state the -completely obvious. Notice below that it is not necessary - to say "returns false otherwise" because this is -implied.
- -// Returns true if the table cannot hold any more entries. -bool IsTableFull(); -- -
When commenting constructors and destructors, remember -that the person reading your code knows what constructors -and destructors are for, so comments that just say -something like "destroys this object" are not useful. -Document what constructors do with their arguments (for -example, if they take ownership of pointers), and what -cleanup the destructor does. If this is trivial, just -skip the comment. It is quite common for destructors not -to have a header comment.
- -Function Definitions
- -If there is anything tricky about how a function does -its job, the function definition should have an -explanatory comment. For example, in the definition -comment you might describe any coding tricks you use, -give an overview of the steps you go through, or explain -why you chose to implement the function in the way you -did rather than using a viable alternative. For instance, -you might mention why it must acquire a lock for the -first half of the function but why it is not needed for -the second half.
- -Note you should not just repeat the comments
-given with the function declaration, in the
-.h file or wherever. It's okay to
-recapitulate briefly what the function does, but the
-focus of the comments should be on how it does it.
Variable Comments
- -In general the actual name of the variable should be -descriptive enough to give a good idea of what the variable -is used for. In certain cases, more comments are required.
-Class Data Members
- -Each class data member (also called an instance -variable or member variable) should have a comment -describing what it is used for. If the variable can take -sentinel values with special meanings, such as a null -pointer or -1, document this. For example:
- - -private: - // Keeps track of the total number of entries in the table. - // Used to ensure we do not go over the limit. -1 means - // that we don't yet know how many entries the table has. - int num_total_entries_; -- -
Global Variables
- -As with data members, all global variables should have -a comment describing what they are and what they are used -for. For example:
- -// The total number of tests cases that we run through in this regression test. -const int kNumTestCases = 6; -- -
Implementation Comments
- -In your implementation you should have comments in tricky, -non-obvious, interesting, or important parts of your code.
-Explanatory Comments
- -Tricky or complicated code blocks should have comments -before them. Example:
- -// Divide result by two, taking into account that x
-// contains the carry from the add.
-for (int i = 0; i < result->size(); i++) {
- x = (x << 8) + (*result)[i];
- (*result)[i] = x >> 1;
- x &= 1;
-}
-
-
-Line Comments
- -Also, lines that are non-obvious should get a comment -at the end of the line. These end-of-line comments should -be separated from the code by 2 spaces. Example:
- -// If we have enough memory, mmap the data portion too. -mmap_budget = max<int64>(0, mmap_budget - index_->length()); -if (mmap_budget >= data_size_ && !MmapData(mmap_chunk_bytes, mlock)) - return; // Error already logged. -- -
Note that there are both comments that describe what -the code is doing, and comments that mention that an -error has already been logged when the function -returns.
- -If you have several comments on subsequent lines, it -can often be more readable to line them up:
- -DoSomething(); // Comment here so the comments line up.
-DoSomethingElseThatIsLonger(); // Two spaces between the code and the comment.
-{ // One space before comment when opening a new scope is allowed,
- // thus the comment lines up with the following comments and code.
- DoSomethingElse(); // Two spaces before line comments normally.
-}
-vector<string> list{// Comments in braced lists describe the next element ..
- "First item",
- // .. and should be aligned appropriately.
- "Second item"};
-DoSomething(); /* For trailing block comments, one space is fine. */
-
-
-nullptr/NULL, true/false, 1, 2, 3...
- -When you pass in a null pointer, boolean, or literal -integer values to functions, you should consider adding a -comment about what they are, or make your code -self-documenting by using constants. For example, -compare:
- -bool success = CalculateSomething(interesting_value, - 10, - false, - NULL); // What are these arguments?? -- -
versus:
- -bool success = CalculateSomething(interesting_value, - 10, // Default base value. - false, // Not the first time we're calling this. - NULL); // No callback. -- -
Or alternatively, constants or self-describing variables:
- -const int kDefaultBaseValue = 10; -const bool kFirstTimeCalling = false; -Callback *null_callback = NULL; -bool success = CalculateSomething(interesting_value, - kDefaultBaseValue, - kFirstTimeCalling, - null_callback); -- -
Don'ts
- -Note that you should never describe the code -itself. Assume that the person reading the code knows C++ -better than you do, even though he or she does not know -what you are trying to do:
- -// Now go through the b array and make sure that if i occurs, -// the next element is i+1. -... // Geez. What a useless comment. -- -
Punctuation, Spelling and Grammar
- -Pay attention to punctuation, spelling, and grammar; it is -easier to read well-written comments than badly written -ones.
-Comments should be as readable as narrative text, with -proper capitalization and punctuation. In many cases, -complete sentences are more readable than sentence -fragments. Shorter comments, such as comments at the end -of a line of code, can sometimes be less formal, but you -should be consistent with your style.
- -Although it can be frustrating to have a code reviewer -point out that you are using a comma when you should be -using a semicolon, it is very important that source code -maintain a high level of clarity and readability. Proper -punctuation, spelling, and grammar help with that -goal.
- -TODO Comments
- -Use TODO comments for code that is temporary,
-a short-term solution, or good-enough but not perfect.
TODOs should include the string
-TODO in all caps, followed by the
-
-name, e-mail address, or other
-identifier of the person
- with the best context
-about the problem referenced by the TODO. The
-main purpose is to have a consistent TODO that
-can be searched to find out how to get more details upon
-request. A TODO is not a commitment that the
-person referenced will fix the problem. Thus when you create
-a TODO, it is almost always your
-
-name
-that is given.
// TODO(kl@gmail.com): Use a "*" here for concatenation operator. -// TODO(Zeke) change this to use relations. --
If your TODO is of the form "At a future
-date do something" make sure that you either include a
-very specific date ("Fix by November 2005") or a very
-specific event ("Remove this code when all clients can
-handle XML responses.").
Deprecation Comments
- -Mark deprecated interface points with DEPRECATED
-comments.
You can mark an interface as deprecated by writing a
-comment containing the word DEPRECATED in
-all caps. The comment goes either before the declaration
-of the interface or on the same line as the
-declaration.
After the word
-DEPRECATED, write your name, e-mail address,
-or other identifier in parentheses.
A deprecation comment must include simple, clear -directions for people to fix their callsites. In C++, you -can implement a deprecated function as an inline function -that calls the new interface point.
- -Marking an interface point DEPRECATED
-will not magically cause any callsites to change. If you
-want people to actually stop using the deprecated
-facility, you will have to fix the callsites yourself or
-recruit a crew to help you.
New code should not contain calls to deprecated -interface points. Use the new interface point instead. If -you cannot understand the directions, find the person who -created the deprecation and ask them for help using the -new interface point.
- - - -Formatting
- -Coding style and formatting are pretty arbitrary, but a - -project is much easier to follow -if everyone uses the same style. Individuals may not agree with every -aspect of the formatting rules, and some of the rules may take -some getting used to, but it is important that all - -project contributors follow the -style rules so that -they can all read and understand -everyone's code easily.
- - - -To help your code conform to our format, we've -created a python script that runs clang-format on it -and performs various other checks.
- -Line Length
- -Each line of text in your code should be at most 80 -characters long.
-We recognize that this rule is -controversial, but so much existing code already adheres -to it, and we feel that consistency is important.
- -Those who favor this rule -argue that it is rude to force them to resize -their windows and there is no need for anything longer. -Some folks are used to having several code windows -side-by-side, and thus don't have room to widen their -windows in any case. People set up their work environment -assuming a particular maximum window width, and 80 -columns has been the traditional standard. Why change -it?
-Proponents of change argue that a wider line can make -code more readable. The 80-column limit is an hidebound -throwback to 1960s mainframes; modern equipment has wide screens that -can easily show longer lines.
-80 characters is the maximum.
- -If a comment line contains an example -command or a literal URL longer than 80 characters, that -line may be longer than 80 characters for ease of cut and -paste.
- -A raw-string literal may have content -that exceeds 80 characters. Except for test code, such literals -should appear near top of a file.
- -An #include statement with a
-long path may exceed 80 columns.
Non-ASCII Characters
- -Non-ASCII characters should be rare, and must use UTF-8 -formatting.
-You shouldn't hard-code user-facing text in source, -even English, so use of non-ASCII characters should be -rare. However, in certain cases it is appropriate to -include such words in your code. For example, if your -code parses data files from foreign sources, it may be -appropriate to hard-code the non-ASCII string(s) used in -those data files as delimiters. More commonly, unittest -code (which does not need to be localized) might -contain non-ASCII strings. In such cases, you should use -UTF-8, since that is an encoding -understood by most tools able to handle more than just -ASCII.
- -Hex encoding is also OK, and encouraged where it
-enhances readability — for example,
-"\xEF\xBB\xBF", or, even more simply,
-u8"\uFEFF", is the Unicode zero-width
-no-break space character, which would be invisible if
-included in the source as straight UTF-8.
Use the u8 prefix
-to guarantee that a string literal containing
-\uXXXX escape sequences is encoded as UTF-8.
-Do not use it for strings containing non-ASCII characters
-encoded as UTF-8, because that will produce incorrect
-output if the compiler does not interpret the source file
-as UTF-8.
You shouldn't use the C++11 char16_t and
-char32_t character types, since they're for
-non-UTF-8 text. For similar reasons you also shouldn't
-use wchar_t (unless you're writing code that
-interacts with the Windows API, which uses
-wchar_t extensively).
Spaces vs. Tabs
- -Use only spaces, and indent 2 spaces at a time.
-We use spaces for indentation. Do not use tabs in your -code. You should set your editor to emit spaces when you -hit the tab key.
- -Function Declarations and Definitions
- -Return type on the same line as function name, parameters -on the same line if they fit. Wrap parameter lists which do -not fit on a single line as you would wrap arguments in a -function call.
-Functions look like this:
- - -ReturnType ClassName::FunctionName(Type par_name1, Type par_name2) {
- DoSomething();
- ...
-}
-
-
-If you have too much text to fit on one line:
- -ReturnType ClassName::ReallyLongFunctionName(Type par_name1, Type par_name2,
- Type par_name3) {
- DoSomething();
- ...
-}
-
-
-or if you cannot fit even the first parameter:
- -ReturnType LongClassName::ReallyReallyReallyLongFunctionName(
- Type par_name1, // 4 space indent
- Type par_name2,
- Type par_name3) {
- DoSomething(); // 2 space indent
- ...
-}
-
-
-Some points to note:
- --
-
- If you cannot fit the return type and the function - name on a single line, break between them. - -
- If you break after the return type of a function - declaration or definition, do not indent. - -
- The open parenthesis is always on the same line as - the function name. - -
- There is never a space between the function name - and the open parenthesis. - -
- There is never a space between the parentheses and - the parameters. - -
- The open curly brace is always at the end of the - same line as the last parameter. - -
- The close curly brace is either on the last line by - itself or (if other style rules permit) on the same - line as the open curly brace. - -
- There should be a space between the close - parenthesis and the open curly brace. - -
- All parameters should be named, with identical - names in the declaration and implementation. - -
- All parameters should be aligned if possible. - -
- Default indentation is 2 spaces. - -
- Wrapped parameters have a 4 space indent. -
If some parameters are unused, comment out the -variable name in the function definition:
- -// Always have named parameters in interfaces.
-class Shape {
- public:
- virtual void Rotate(double radians) = 0;
-};
-
-// Always have named parameters in the declaration.
-class Circle : public Shape {
- public:
- virtual void Rotate(double radians);
-};
-
-// Comment out unused named parameters in definitions.
-void Circle::Rotate(double /*radians*/) {}
-
-
-// Bad - if someone wants to implement later, it's not clear what the
-// variable means.
-void Circle::Rotate(double) {}
-
-
-Lambda Expressions
- -Format parameters and bodies as for any other function, and capture -lists like other comma-separated lists.
-For by-reference captures, do not leave a space between the -ampersand (&) and the variable name.
-int x = 0;
-auto add_to_x = [&x](int n) { x += n; };
-
-Short lambdas may be written inline as function arguments.
-std::set<int> blacklist = {7, 8, 9};
-std::vector<int> digits = {3, 9, 1, 8, 4, 7, 1};
-digits.erase(std::remove_if(digits.begin(), digits.end(), [&blacklist](int i) {
- return blacklist.find(i) != blacklist.end();
- }),
- digits.end());
-
-
-Function Calls
- -Either write the call all on a single line, wrap the -arguments at the parenthesis, or start the arguments on a new -line indented by four spaces and continue at that 4 space -indent. In the absence of other considerations, use the -minimum number of lines, including placing multiple arguments -on each line where appropriate.
-Function calls have the following format:
-bool retval = DoSomething(argument1, argument2, argument3); -- -
If the arguments do not all fit on one line, they -should be broken up onto multiple lines, with each -subsequent line aligned with the first argument. Do not -add spaces after the open paren or before the close -paren:
-bool retval = DoSomething(averyveryveryverylongargument1, - argument2, argument3); -- -
Arguments may optionally all be placed on subsequent -lines with a four space indent:
-if (...) {
- ...
- ...
- if (...) {
- DoSomething(
- argument1, argument2, // 4 space indent
- argument3, argument4);
- }
-
-
-Put multiple arguments on a single line to reduce the -number of lines necessary for calling a function unless -there is a specific readability problem. Some find that -formatting with strictly one argument on each line is -more readable and simplifies editing of the arguments. -However, we prioritize for the reader over the ease of -editing arguments, and most readability problems are -better addressed with the following techniques.
- -If having multiple arguments in a single line decreases -readability due to the complexity or confusing nature of the -expressions that make up some arguments, try creating -variables that capture those arguments in a descriptive name:
-int my_heuristic = scores[x] * y + bases[x]; -bool retval = DoSomething(my_heuristic, x, y, z); -- -
Or put the confusing argument on its own line with -an explanatory comment:
-bool retval = DoSomething(scores[x] * y + bases[x], // Score heuristic. - x, y, z); -- -
If there is still a case where one argument is -significantly more readable on its own line, then put it on -its own line. The decision should be specific to the argument -which is made more readable rather than a general policy.
- -Sometimes arguments form a structure that is important -for readability. In those cases, feel free to format the -arguments according to that structure:
-// Transform the widget by a 3x3 matrix. -my_widget.Transform(x1, x2, x3, - y1, y2, y3, - z1, z2, z3); -- -
Braced Initializer List Format
- -Format a braced initializer list -exactly like you would format a function call in its place.
-If the braced list follows a name (e.g. a type or
-variable name), format as if the {} were the
-parentheses of a function call with that name. If there
-is no name, assume a zero-length name.
// Examples of braced init list on a single line.
-return {foo, bar};
-functioncall({foo, bar});
-pair<int, int> p{foo, bar};
-
-// When you have to wrap.
-SomeFunction(
- {"assume a zero-length name before {"},
- some_other_function_parameter);
-SomeType variable{
- some, other, values,
- {"assume a zero-length name before {"},
- SomeOtherType{
- "Very long string requiring the surrounding breaks.",
- some, other values},
- SomeOtherType{"Slightly shorter string",
- some, other, values}};
-SomeType variable{
- "This is too long to fit all in one line"};
-MyType m = { // Here, you could also break before {.
- superlongvariablename1,
- superlongvariablename2,
- {short, interior, list},
- {interiorwrappinglist,
- interiorwrappinglist2}};
-
-
-Conditionals
- -Prefer no spaces inside parentheses. The if
-and else keywords belong on separate lines.
There are two acceptable formats for a basic -conditional statement. One includes spaces between the -parentheses and the condition, and one does not.
- -The most common form is without spaces. Either is -fine, but be consistent. If you are modifying a -file, use the format that is already present. If you are -writing new code, use the format that the other files in -that directory or project use. If in doubt and you have -no personal preference, do not add the spaces.
- -if (condition) { // no spaces inside parentheses
- ... // 2 space indent.
-} else if (...) { // The else goes on the same line as the closing brace.
- ...
-} else {
- ...
-}
-
-
-If you prefer you may add spaces inside the -parentheses:
- -if ( condition ) { // spaces inside parentheses - rare
- ... // 2 space indent.
-} else { // The else goes on the same line as the closing brace.
- ...
-}
-
-
-Note that in all cases you must have a space between
-the if and the open parenthesis. You must
-also have a space between the close parenthesis and the
-curly brace, if you're using one.
if(condition) { // Bad - space missing after IF.
-if (condition){ // Bad - space missing before {.
-if(condition){ // Doubly bad.
-
-
-if (condition) { // Good - proper space after IF and before {.
-
-
-Short conditional statements may be written on one
-line if this enhances readability. You may use this only
-when the line is brief and the statement does not use the
-else clause.
if (x == kFoo) return new Foo(); -if (x == kBar) return new Bar(); -- -
This is not allowed when the if statement has an
-else:
// Not allowed - IF statement on one line when there is an ELSE clause -if (x) DoThis(); -else DoThat(); -- -
In general, curly braces are not required for
-single-line statements, but they are allowed if you like
-them; conditional or loop statements with complex
-conditions or statements may be more readable with curly
-braces. Some
-projects require that an
-if must always always have an accompanying
-brace.
if (condition)
- DoSomething(); // 2 space indent.
-
-if (condition) {
- DoSomething(); // 2 space indent.
-}
-
-
-However, if one part of an
-if-else statement uses curly
-braces, the other part must too:
// Not allowed - curly on IF but not ELSE
-if (condition) {
- foo;
-} else
- bar;
-
-// Not allowed - curly on ELSE but not IF
-if (condition)
- foo;
-else {
- bar;
-}
-
-
-// Curly braces around both IF and ELSE required because
-// one of the clauses used braces.
-if (condition) {
- foo;
-} else {
- bar;
-}
-
-
-Loops and Switch Statements
- -Switch statements may use braces for blocks. Annotate
-non-trivial fall-through between cases.
-Braces are optional for single-statement loops.
-Empty loop bodies should use {} or continue.
case blocks in switch
-statements can have curly braces or not, depending on
-your preference. If you do include curly braces they
-should be placed as shown below.
If not conditional on an enumerated value, switch
-statements should always have a default case
-(in the case of an enumerated value, the compiler will
-warn you if any values are not handled). If the default
-case should never execute, simply
-assert:
switch (var) {
- case 0: { // 2 space indent
- ... // 4 space indent
- break;
- }
- case 1: {
- ...
- break;
- }
- default: {
- assert(false);
- }
-}
-
-Braces are optional for single-statement loops.
- -for (int i = 0; i < kSomeNumber; ++i)
- printf("I love you\n");
-
-for (int i = 0; i < kSomeNumber; ++i) {
- printf("I take it back\n");
-}
-
-
-
-Empty loop bodies should use {} or
-continue, but not a single semicolon.
while (condition) {
- // Repeat test until it returns false.
-}
-for (int i = 0; i < kSomeNumber; ++i) {} // Good - empty body.
-while (condition) continue; // Good - continue indicates no logic.
-
-
-while (condition); // Bad - looks like part of do/while loop. -- -
Pointer and Reference Expressions
- -No spaces around period or arrow. Pointer operators do not -have trailing spaces.
-The following are examples of correctly-formatted -pointer and reference expressions:
- -x = *p; -p = &x; -x = r.y; -x = r->y; -- -
Note that:
- --
-
- There are no spaces around the period or arrow when - accessing a member. - -
- Pointer operators have no space after the
-
*or&.
-
When declaring a pointer variable or argument, you may -place the asterisk adjacent to either the type or to the -variable name:
- -// These are fine, space preceding. -char *c; -const string &str; - -// These are fine, space following. -char* c; // but remember to do "char* c, *d, *e, ...;"! -const string& str; -- -
char * c; // Bad - spaces on both sides of * -const string & str; // Bad - spaces on both sides of & -- -
You should do this consistently within a single -file, -so, when modifying an existing file, use the style in -that file.
- -Boolean Expressions
- -When you have a boolean expression that is longer than the -standard line length, be -consistent in how you break up the lines.
-In this example, the logical AND operator is always at -the end of the lines:
- -if (this_one_thing > this_other_thing &&
- a_third_thing == a_fourth_thing &&
- yet_another && last_one) {
- ...
-}
-
-
-Note that when the code wraps in this example, both of
-the && logical AND operators are at
-the end of the line. This is more common in Google code,
-though wrapping all operators at the beginning of the
-line is also allowed. Feel free to insert extra
-parentheses judiciously because they can be very helpful
-in increasing readability when used
-appropriately. Also note that you should always use
-the punctuation operators, such as
-&& and ~, rather than
-the word operators, such as and and
-compl.
Return Values
- -Do not needlessly surround the return
-expression with parentheses.
Use parentheses in return expr; only
-where you would use them in x = expr;.
return result; // No parentheses in the simple case. -// Parentheses OK to make a complex expression more readable. -return (some_long_condition && - another_condition); -- -
return (value); // You wouldn't write var = (value); -return(result); // return is not a function! -- -
Variable and Array Initialization
- -Your choice of =, (), or
-{}.
You may choose between =,
-(), and {}; the following are
-all correct:
int x = 3;
-int x(3);
-int x{3};
-string name = "Some Name";
-string name("Some Name");
-string name{"Some Name"};
-
-
-Be careful when using a braced initialization list {...}
-on a type with an std::initializer_list constructor.
-A nonempty braced-init-list prefers the
-std::initializer_list constructor whenever
-possible. Note that empty braces {} are special, and
-will call a default constructor if available. To force the
-non-std::initializer_list constructor, use parentheses
-instead of braces.
vector<int> v(100, 1); // A vector of 100 1s.
-vector<int> v{100, 1}; // A vector of 100, 1.
-
-
-Also, the brace form prevents narrowing of integral -types. This can prevent some types of programming -errors.
- -int pi(3.14); // OK -- pi == 3.
-int pi{3.14}; // Compile error: narrowing conversion.
-
-
-Preprocessor Directives
- -The hash mark that starts a preprocessor directive should -always be at the beginning of the line.
-Even when preprocessor directives are within the body -of indented code, the directives should start at the -beginning of the line.
- -// Good - directives at beginning of line
- if (lopsided_score) {
-#if DISASTER_PENDING // Correct -- Starts at beginning of line
- DropEverything();
-# if NOTIFY // OK but not required -- Spaces after #
- NotifyClient();
-# endif
-#endif
- BackToNormal();
- }
-
-
-// Bad - indented directives
- if (lopsided_score) {
- #if DISASTER_PENDING // Wrong! The "#if" should be at beginning of line
- DropEverything();
- #endif // Wrong! Do not indent "#endif"
- BackToNormal();
- }
-
-
-Class Format
- -Sections in public, protected and
-private order, each indented one space.
The basic format for a class declaration (lacking the -comments, see Class -Comments for a discussion of what comments are -needed) is:
- -class MyClass : public OtherClass {
- public: // Note the 1 space indent!
- MyClass(); // Regular 2 space indent.
- explicit MyClass(int var);
- ~MyClass() {}
-
- void SomeFunction();
- void SomeFunctionThatDoesNothing() {
- }
-
- void set_some_var(int var) { some_var_ = var; }
- int some_var() const { return some_var_; }
-
- private:
- bool SomeInternalFunction();
-
- int some_var_;
- int some_other_var_;
-};
-
-
-Things to note:
- --
-
- Any base class name should be on the same line as - the subclass name, subject to the 80-column limit. - -
- The
public:,protected:, - andprivate:keywords should be indented - one space.
-
- - Except for the first instance, these keywords - should be preceded by a blank line. This rule is - optional in small classes. - -
- Do not leave a blank line after these - keywords. - -
- The
publicsection should be first, - followed by theprotectedand finally the -privatesection.
-
- - See Declaration - Order for rules on ordering declarations within - each of these sections. -
Constructor Initializer Lists
- -Constructor initializer lists can be all on one line or -with subsequent lines indented four spaces.
-There are two acceptable formats for initializer -lists:
- -// When it all fits on one line:
-MyClass::MyClass(int var) : some_var_(var), some_other_var_(var + 1) {}
-
-
-or
- -// When it requires multiple lines, indent 4 spaces, putting the colon on
-// the first initializer line:
-MyClass::MyClass(int var)
- : some_var_(var), // 4 space indent
- some_other_var_(var + 1) { // lined up
- ...
- DoSomething();
- ...
-}
-
-
-Namespace Formatting
- -The contents of namespaces are not indented.
-Namespaces do not add an -extra level of indentation. For example, use:
- -namespace {
-
-void foo() { // Correct. No extra indentation within namespace.
- ...
-}
-
-} // namespace
-
-
-Do not indent within a namespace:
- -namespace {
-
- // Wrong. Indented when it should not be.
- void foo() {
- ...
- }
-
-} // namespace
-
-
-When declaring nested namespaces, put each namespace -on its own line.
- -namespace foo {
-namespace bar {
-
-
-Horizontal Whitespace
- -Use of horizontal whitespace depends on location. Never put -trailing whitespace at the end of a line.
-General
- -void f(bool b) { // Open braces should always have a space before them.
- ...
-int i = 0; // Semicolons usually have no space before them.
-// Spaces inside braces for braced-init-list are optional. If you use them,
-// put them on both sides!
-int x[] = { 0 };
-int x[] = {0};
-
-// Spaces around the colon in inheritance and initializer lists.
-class Foo : public Bar {
- public:
- // For inline function implementations, put spaces between the braces
- // and the implementation itself.
- Foo(int b) : Bar(), baz_(b) {} // No spaces inside empty braces.
- void Reset() { baz_ = 0; } // Spaces separating braces from implementation.
- ...
-
-
-Adding trailing whitespace can cause extra work for -others editing the same file, when they merge, as can -removing existing trailing whitespace. So: Don't -introduce trailing whitespace. Remove it if you're -already changing that line, or do it in a separate -clean-up -operation (preferably when no-one -else is working on the file).
- -Loops and Conditionals
- -if (b) { // Space after the keyword in conditions and loops.
-} else { // Spaces around else.
-}
-while (test) {} // There is usually no space inside parentheses.
-switch (i) {
-for (int i = 0; i < 5; ++i) {
-// Loops and conditions may have spaces inside parentheses, but this
-// is rare. Be consistent.
-switch ( i ) {
-if ( test ) {
-for ( int i = 0; i < 5; ++i ) {
-// For loops always have a space after the semicolon. They may have a space
-// before the semicolon, but this is rare.
-for ( ; i < 5 ; ++i) {
- ...
-
-// Range-based for loops always have a space before and after the colon.
-for (auto x : counts) {
- ...
-}
-switch (i) {
- case 1: // No space before colon in a switch case.
- ...
- case 2: break; // Use a space after a colon if there's code after it.
-
-
-Operators
- -// Assignment operators always have spaces around them. -x = 0; - -// Other binary operators usually have spaces around them, but it's -// OK to remove spaces around factors. Parentheses should have no -// internal padding. -v = w * x + y / z; -v = w*x + y/z; -v = w * (x + z); - -// No spaces separating unary operators and their arguments. -x = -5; -++x; -if (x && !y) - ... -- -
Templates and Casts
- -// No spaces inside the angle brackets (< and >), before -// <, or between >( in a cast -vector<string> x; -y = static_cast<char*>(x); - -// Spaces between type and pointer are OK, but be consistent. -vector<char *> x; -set<list<string>> x; // Permitted in C++11 code. -set<list<string> > x; // C++03 required a space in > >. - -// You may optionally use symmetric spacing in < <. -set< list<string> > x; -- -
Vertical Whitespace
- -Minimize use of vertical whitespace.
-This is more a principle than a rule: don't use blank -lines when you don't have to. In particular, don't put -more than one or two blank lines between functions, -resist starting functions with a blank line, don't end -functions with a blank line, and be discriminating with -your use of blank lines inside functions.
- -The basic principle is: The more code that fits on one -screen, the easier it is to follow and understand the -control flow of the program. Of course, readability can -suffer from code being too dense as well as too spread -out, so use your judgement. But in general, minimize use -of vertical whitespace.
- -Some rules of thumb to help when blank lines may be -useful:
- --
-
- Blank lines at the beginning or end of a function - very rarely help readability. - -
- Blank lines inside a chain of if-else blocks may - well help readability. -
Exceptions to the Rules
- -The coding conventions described above are mandatory. -However, like all good rules, these sometimes have exceptions, -which we discuss here.
- - - -Existing Non-conformant Code
- -You may diverge from the rules when dealing with code that -does not conform to this style guide.
-If you find yourself modifying code that was written -to specifications other than those presented by this -guide, you may have to diverge from these rules in order -to stay consistent with the local conventions in that -code. If you are in doubt about how to do this, ask the -original author or the person currently responsible for -the code. Remember that consistency includes -local consistency, too.
- -Parting Words
- -Use common sense and BE CONSISTENT.
- -If you are editing code, take a few minutes to look at the
-code around you and determine its style. If they use spaces
-around their if clauses, you should, too. If their
-comments have little boxes of stars around them, make your
-comments have little boxes of stars around them too.
The point of having style guidelines is to have a common -vocabulary of coding so people can concentrate on what you are -saying, rather than on how you are saying it. We present global -style rules here so people know the vocabulary. But local style -is also important. If code you add to a file looks drastically -different from the existing code around it, the discontinuity -throws readers out of their rhythm when they go to read it. Try -to avoid this.
- - - -OK, enough writing about writing code; the code itself is much -more interesting. Have fun!
- -- -
Revision 4.45
- -- ', ('list',)),
- ('