Coding Standards for the Parma Polyhedra Library ================================================ Pre and post increment and decrement operators ---------------------------------------------- All other things being equal, always prefer preincrement and predecrement to postincrement and postdecrement. Length of source lines ---------------------- Avoid source lines longer than 78 characters. Block closures -------------- Try to make clear what is being closed. For example: 1) namespace Parma_Polyhedra_Library { ... } // namespace Parma_Polyhedra_Library 2) extern "C" { ... } // extern "C" 3) #ifndef PPL_Class_defs_hh ... #endif // !defined(PPL_Class_defs_hh) Namespace indentation --------------------- The entire library is in its own namespace. We sometimes specialize std::swap() and std::swap_iter(). Other namespaces may be involved but only in restricted contexts. Therefore, we have unindented namespace-level declarations, thus saving some precious horizontal space. For example: namespace Parma_Polyhedra_Library { non-empty lines here start at column 0; } // namespace Parma_Polyhedra_Library If you use emacs, you may want to put the following two lines in your .emacs: ;; Disable indentation when in namespace blocks. (c-set-offset 'innamespace 0) Standards for Documenting the Project with Doxygen ================================================== 1) All code entities (classes, structs, enums, variables, methods, functions, etc.) should be provided with a brief Doxygen comment. Brief comments are normally obtained as follows: //! Brief comment for class C. class C { ... }; If the comment is multi-line, then either of the following syntax can be adopted: //! \brief //! A brief comment for class C, that is a bit too long //! to be placed in a single line. class C { ... }; or /*! \brief A brief comment for class C, that is a bit too long to be placed in a single line. */ class C { ... }; 2) A *friend* declaration of a function should NOT be provided with a Doxygen comment. Rather, it is the very declaration of the function (which should be found outside of the class) that has to be documented. 3) When needed or useful, brief comments should be followed by detailed Doxygen comments. //! Brief comment for class C. /*! More details on class C. Even more details. */ class C { ... }; In the produced documentation, the brief comment will be automatically repeated just before the detailed comment, so that bare repetitions should be avoided. 4) In the source files, detailed comments should be placed immediately after the brief ones, so that all the documentation pertinent to a code entity is kept in a single file (typically, the *.defs.hh file). 5) It is also possible to merge the brief and detailed comments inside a single (detailed) Doxygen documentation block, as follows: /*! \brief Brief comment for class C. More details on class C. Even more details. */ class C { ... }; The first paragraph break (in this case, the empty line) marks the separation between the brief and the detailed part. Note that all the uses of \param, \result and \exception special commands will automatically cause a paragraph break, therefore starting the detailed part. This will happen even when using the //! style documentation blocks and the \brief command. 6) Brief Doxygen comments should be brief (indeed). If more than two lines are required, then the comment should be split into a brief part and a detailed part. 7) Code entities or details that should not be visible to the end-user (but that are useful for the developers) should be surrounded by #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS //! ... doxygen comments ... #endif // PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS so that they will only appear in the developer's reference. Note that the above preprocessing flags are not necessary (and should therefore be avoided) when documenting: - a private member of a class (because private members never appear in the user manual); - a public member of a class that is not documented (because even the documented members of an undocumented class are automatically filtered out of the user manual). 8) Merging multiple comment blocks is not allowed by Doxygen. Thus, the technique described in point 4) above is useless when we want an end-user comment block to be integrated, in the developer's reference only, by further comments. In such a case, a single comment block should be used as follows: // ... doxygen comments for both user and developer ... // \if Include_Implementation_Details // ... doxygen comments for developer only ... // \endif // ... doxygen comments for both user and developer ... 9) The documentation of those functions that are neither methods nor friends of a given class, but are related in some way to that class, should be made part of the documentation of the class. This is obtained by using the Doxygen \relates special command as follows: /*! \relates */ It seems that, in order to correctly match function declarations and definitions, the above command should be placed in both places. Typically, this will be the only kind of Doxygen command occurring in *.inlines.hh and *.cc source files. If is a templatic class, the arguments of the template (as well as the angle brackets) should be omitted. The namespace qualification of the class can be omitted, provided the comment block is included in the namespace scope. 10) If the \return or \param special commands are used, then these have to be placed after the brief doxygen comment. The \result special command, if present, should come before any \param command. The \exception special command, if present, should come after any \param command. All the parameters of the function should be provided by the corresponding \param command, respecting their textual order, separating them with a blank line. The documentation of each parameter should start at the line immediately following the \param command. Typically, the list of parameters should be formatted as follows, where the \return command is optional. /*! \brief The brief description. The detailed description, if any. \return Documentation for the return value, if provided. \param p1 Documentation for p1; \param p2 Documentation for p2; other documentation for p2; \param p3 Documentation for p3. \exception exception_type1 Documentation for the exceptions of type exception_type1; \exception exception_type2 Documentation for the exceptions of type exception_type2. Another piece of detailed description, if needed. */ int foo(const bar& p1, const bar& p2, int p3);