All submitted code must adhere to the style guidelines given below (which are largely based on the C++ STL/Boost style guidelines). Note that this style may be different from ones you have seen before (if you’ve seen any). That is partially intentional: in a professional setting you will have to get used to writing code that adheres to different style requirements. It’s worth bearing in mind that implementation “style” (e.g., proper use of abstract base class, templates and generic types, exceptions, etc.) is much more important than any particular layout style.
C++ source files should have the extension
.cpp
. Header files should have the extension.hpp
.Every “computational unit” (function, class, type, etc.) must have a block-style comment before it explaining what its purpose is. For functions, this comment takes the form
/* name(argument1, argument2, ...) Short description of what the function does (NOT how it does it). - argument1: Description of the purpose of argument 1 - argument2: Description of the purpose of argument 2 Returns: description of the return value, if any, of the function. Assumes: details any assumptions about the global state and arguments that the function relies on. Ensures: details what state(s) the arguments and global state will be in after the function successfully completes. Throws: if the function *itself* throws any exceptions, they should be detailed. */
The exception to this rule is the
main
function, whose arguments are standardized and whose function is already documented, in the comment at the top of the file.Argument descriptions should note whether an argument will be modified.
const
-correctness requires that all non-primitive arguments that are not intentionally modified be passed asconst
references. (If an argument isconst
or primitive then you do not need to also state that it is not modified; it’s obvious.)Every file should begin with a block comment of the form
/* filename.cc One-line desciption of this file's purpose. Author's name Date of last revision. Longer (1-ish paragraph) description of the file's content. In particular, highlight any functions, classes, etc. that are intended for use outside the file. */
For the file containing
main
, this comment should describe not just what the file is for, but what the whole program is for: what it does, how the user interacts with it, etc. If any special compilation flags are required, you can put them here also. (The comment at the beginning of the main file is also a good place to put any comments to me, your instructor!)If you are resubmitting a file/project, then you should replace the date of revision with a changelog, a record of everything you changed from your first submission. For example:
Changelog: Jan-22 first submission Jan-31 resubmission: fixed off-by-one bug in print_name() function added error checking code to read_name() function fixed indentation and code style
If you resubmit multiple times, add a new changelog entry for each submission, each time describing what you changed from the previous submission.
Use spaces rather than tabs, with four-space indentation. You can configure your editor so that when you press Tab it inserts four spaces.
For all block constructs, the opening brace is on the same line as the opening statement (
if(...) {
). This includes functions and classes, too! The body of the block is indented one level. The closing brace is indented to the parent level (e.g., the closing}
for the if-statement above would be vertically aligned with thei
inif
).Type, class, struct, and function names are all lower-case, with multiple words separated by underscores (e.g.,
sort_list
). Names of functions and functors should be verb-like (sort
) when they are destructive (modify one or more of their arguments in place), be past-tense when they return a new object modified in some way (sorted
), and be predicates when they return a Boolean-like true/false value (is_sorted
). Names of type-like objects should be abstract nouns (list
,fruit
, etc.).(Types and functions all share the same naming rules partly because classes can be made to act like functions, by overloading
()
. In general, C++ empasizes the behavior of an object rather than its underlying type. We care about whether a value acts like a container, or a numeric value, or a function, etc.; i.e., what operators it overloads. We don’t care about whether its implemented as a function or a class or a typedef for something.)Variable names are lowercase, with separate words separated by underscores. Variable names should be noun-like (
element_count
) and should be long enough to be explanatory, but not so long as to hinder readability. (element_count
is good;ec
is too short,number_of_elements_in_list
is too long.) The single-letter variable namesi
,j
, andk
are acceptable as loop variables, if no other name would be better. (Similarly, when dealing with coordinates,x
andy
are perectly fine variable names.)Some abbreviations for names are common enough to be semi-standard:
len
forlength
,Template type names (i.e., the arguments to a
template<...>
qualifier) should start with an upper-case letter, and be written in CamelCase (no underscore separators between words, separate words capitalized), but otherwise follow the rule for naming types: use abstract nouns.Don’t use case-fallthrough in a
switch
statement without a good reason. If you do use fallthrough, you must have a comment explaining what is happening.main
must end with areturn
statement, returning a value. Never callmain
within your program (this is not just a stylistic choice but it actually required by C++; ignore anyone who tells you otherwise).Try not to use the pre/post-increment operators as part of a larger expression, unless the meaning is absolutely clear. E.g., instead of this
a[x++] = b[--y]; // What?
write
y--; a[x] = b[y]; x++;
which makes the order in which things happen absolutely clear.
Prefer
vector
to primitive arrays. If you need the speed of an array, you can use the overloaded[]
operator, but for safety you should prefer.at()
.