CppCodingConventions
Please see CodingConventions and GenericCodingConventions for language-independent rules.
Contents |
Header Files
All header files should follow the pattern below:
/*
// $Id: Snafu.h#1 $
// ... Project boilerplate ...
*/
#ifndef Fennel_Snafu_Included
#define Fennel_Snafu_Included
#include "fennel/device/Fiasco.h"
FENNEL_BEGIN_NAMESPACE
/**
* A Snafu is a rather mundane kind of Fiasco.
*
* @author Polly Nomial
* @version $Id: Snafu.h#1 $
*/
class Snafu : public Fiasco
{
int calamityLevel;
explicit Snafu(int calamityLevelInit);
...
};
...
FENNEL_END_NAMESPACE
#endif
// End Snafu.h
Notes:
- Standard Perforce $Id:$ tag in file header
- Conditional compilation guards against reinclusion
- Includes are outside the project-specific namespace block
- All other code is inside the project-specific namespace block
- Class documentation comment includes @author and @version tags
- End-of-file comment
The InlineMethods page provides guidelines on use of method inlining.
Functional .cpp Files
All .cpp files containing functional code should follow the pattern below:
/*
* $Id: Snafu.cpp#1 $
* ... Project boilerplate ...
*/
#include "fennel/common/CommonPreamble.h"
#include "fennel/device/Snafu.h"
#include "fennel/device/Awol.h"
FENNEL_BEGIN_CPPFILE("$Id: Snafu.cpp#1 $");
Snafu::Snafu(int calamityLevelInit)
{
calamityLevel = calamityLevelInit;
}
...
FENNEL_END_CPPFILE("$Id: Snafu.cpp #1 $");
// End Snafu.cpp
Notes:
- Standard Perforce $Id:$ tag in file header
- First include is always project-specific preamble
- Second include should usually be matching header file; this helps to catch problems with implicit header dependencies
- Other includes follow
- All functional code is enclosed by project-specific BEGIN/END_CPPFILE lines; in the future we can use the Perforce $Id:$ tag expansions to identify file versions in assertions.
- End-of-file comment
Test .cpp Files
Test code follows the same pattern as functional code, except that it is not included in the project namespace. Instead, it issues a using directive to import the project namespace:
/*
* $Id: SnafuTest.cpp#1 $
* ... Project boilerplate ...
*/
#include "fennel/common/CommonPreamble.h"
#include "fennel/device/Snafu.h"
#include "fennel/test/TestBase.h"
using namespace fennel;
class SnafuTest : public TestBase
{
void testMurphysLaw();
public:
explicit SnafuTest()
{
FENNEL_UNIT_TEST_CASE(SnafuTest,testMurphysLaw);
}
}
...
FENNEL_UNIT_TEST_SUITE(SnafuTest);
// End SnafuTest.cpp
TBD: rationale for this setup, and whether it's possible to introduce a test namespace.
Documentation Comments
Use of all documentation constructs recognized by doxygen is encouraged, but wherever an equivalent Javadoc construct exists, use that instead (e.g. use /** instead of //! to introduce a doc comment).
When inserting a reference to the SQL standard specification from a comment, use this convention.
Idioms
Eigenbase C++ code contains a number of common idioms.
- Always prefix constructors with the
explicitkeyword unless you're sure you want implicit conversions. - A constructor parameter matching member variable
fooshould be calledfooInit; don't usethis->foobecause it's not possible to use that pattern for reference initialization. (This is different from Java.) See Snafu example earlier in this document. - Use const wherever possible.
- Follow the C99 standard when declaring variables with sized integer types (e.g.
uint16_t,int64_t). - Pointers vs. references: use references for addresses that can't change and can't be NULL. Compiler optimizers are allowed to take advantage of this information. Use pointers for anything else.
- Use automatic memory management such as boost
shared_ptrand STLvectorwherever possible. If you find yourself needing explicitdeletestatements, in most cases it means you're doing something wrong. - Avoid declaring constants at namespace scope unless they are truly global; most constants should be declared inside of classes or subnamespaces instead. Likewise for functions. Enums declared at namespace scope should use a prefixing convention for enum value names.
Assertions
- Use the standard
assertmacro for assertions that should only be enabled in debug builds. These will not be compiled into optimized builds, soassertis useful for performance-sensitive code. - Use the Fennel-specific
permAssertmacro for assertions that should be enabled even in optimized builds. In code that is not performance-sensitive, it is preferable to usepermAssertbecause it results in better field diagnostics in case of an internal error.
TBD
- Tracing