| [/============================================================================ |
| Boost.Geometry (aka GGL, Generic Geometry Library) |
| |
| Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. |
| Copyright (c) 2008-2012 Bruno Lalande, Paris, France. |
| Copyright (c) 2009-2013 Mateusz Loskot, London, UK. |
| |
| Use, modification and distribution is subject to the Boost Software License, |
| Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
| http://www.boost.org/LICENSE_1_0.txt) |
| |
| =============================================================================/] |
| |
| [section:guidelines Guidelines for developers] |
| |
| This library is maintained by several developers, and in order it to have |
| a consistent design, look and feel, a few guidelines need to be followed. |
| |
| Rules of [@boost:/development/requirements.html Boost Library Requirements and Guidelines] |
| and [@boost:/development/header.html Boost Header Policy] always have highest authority. |
| |
| Generally, prefer style of modern C++, conventions as used in latest C++ standard |
| document and C++ Standard Library. Boost.Spirit is a good example of |
| how to write and format high quality C++ code. |
| |
| Some guidelines specific to Boost.Geometry library are outlined below. |
| |
| [heading Code structure] |
| |
| * Every file shall have header with copyright and license information. |
| * Do not put any history or revision information in comments in source files. |
| Log it with VCS used in the Boost project. |
| * Every header shall have `#include` guard based on header path and file name: |
| `` |
| #ifndef BOOST_GEOMETRY_<DIR1>_<DIR2>_<FILE>_HPP |
| #define BOOST_GEOMETRY_<DIR1>_<DIR2>_<FILE>_HPP |
| ... |
| #endif // BOOST_GEOMETRY_<DIR1>_<DIR2>_<FILE>_HPP |
| `` |
| * `#include` directives shall be ordered according the most authoritative header: |
| * C Standard Library (using C++ library names, i.e. `<cstdlib>`) |
| * C++ Standard Library |
| * Boost C++ Libraries |
| * Boost.Geometry headers |
| * Other 3rd-party headers (only if applicable! in some samples only) |
| * Header within these sections should be ordered alphabetically, especially if there are many of them included. |
| * Namespaces don't increase the level of indentation. |
| In all other cases braces increase the level of indentation. |
| `` |
| namespace boost { namespace geometry |
| { |
| |
| namespace mynewspace |
| { |
| |
| template <typename Point> |
| struct my_new_model |
| { |
| typedef point_type; |
| } |
| |
| } // namespace mynewspace |
| |
| }} // namespace boost::geometry |
| `` |
| * Namespace closing brace should have comment with the namespace name. |
| * All non-public headers should be placed into `boost/geometry/detail` or |
| `boost/geometry/*/detail` directory, depending on component level. |
| * All non-public names should reside in the `boost::geometry::detail` or |
| `boost::geometry::*::detail` namespace, depending on component level. |
| * All traits should be placed in dedicated `boost::geometry::traits` or |
| `boost::geometry::*::traits` namespace |
| * All tag dispatching routines should be placed in dedicated |
| `boost::geometry::*::dispatch` namespace. |
| * Access specifiers for class members shall be orderd as public first, then protected and private at the bottom. |
| The public members define class interface, thus they are of the highest interested for users, so show them first. |
| * Exceptions to this rule are allowed for typedef aliases required to be defined first. |
| |
| [heading Code formatting and indentation] |
| |
| * The code is indented with spaces, 4 spaces per tab. |
| * The preferred line length is 80 characters, with maximum length of 100. |
| * The limit is relaxed for very long string literals (e.g. Well-Known Text with data used in tests and examples). |
| * Member/base initialization list for constructors on the same line, |
| if it's small (1-2 members) or 1 member/base per line with leading comma on the left: |
| ``` |
| struct T |
| { |
| T(int a, int b) |
| : a(a) |
| , b(b) |
| {} |
| |
| int a; |
| int b; |
| }; |
| ``` |
| * Template declaration with long template parameter list shall be formatted |
| with one template parameter per line, all parameters indented, |
| but `<` and `>` brackets not indented: |
| ``` |
| template |
| < |
| typename T, |
| typename P, |
| typename C = std::vector<Point> |
| > |
| struct polygon |
| { |
| typedef typename boost::remove_const |
| < |
| typename traits::point_type<T>::type |
| >::type type |
| }; |
| ``` |
| * References and pointers should be formatted emphasizing type, not syntax: |
| ``` |
| T const& t; |
| T* t; |
| T* const t; |
| T const* t; |
| T const* const t; |
| ``` |
| * Braces enclosing block of code (if-else, loops) should be placed in separate lines |
| ``` |
| if (expr) |
| { |
| } |
| ``` |
| * Parentheses around expressions should not be pre/post-fixed with spaces. |
| |
| [heading Naming conventions] |
| |
| * All names follow style of the C++ Standard, lowercase with words separated with underscore `_`, |
| unless otherwise specified (see other rules). |
| * Template parameters are named in CamelCase. |
| * Concepts are named in CamelCase. |
| * Name of a class data member shall start with `m_` prefix. |
| The Boost sample header gives no prefix or suffix at all. |
| However, the `m_` prefix is used in some (not many) Boost libraries as well (e.g. math/tools/remez). |
| * All macro names shall be in upper-case, words separated with underscore `_`. |
| * All macro names shall start with `BOOST_GEOMETRY_`. |
| * All non-public macro names should start with `BOOST_GEOMETRY_DETAIL_` (not used often yet, if at all). |
| * All public names should reside in the `boost::geometry` namespace. |
| Nested namespaces are also possible. |
| * Avoid cryptic names and abbreviations for elements used in wider context (e.g. types, functions). |
| Short names are allowed if context of use is local, narrow and easily tracable |
| For example, use of `it` for `iterator` in body of a loop in function: |
| ``` |
| template <typename Range, typename Functor> |
| static inline void apply(Range& range, Functor& f) |
| { |
| for (typename boost::range_iterator<Range>::type it = boost::begin(range); |
| it != boost::end(range); ++it) |
| { |
| f(*it); |
| } |
| } |
| ``` |
| |
| [heading C++ use conventions] |
| |
| * Keyword struct is preferred either for POD structures, or for classes used at compile-time |
| like metafunctions, tags, traits, etc. |
| * Keyword class is preferred for classes meant to produce actual objects, which have methods |
| and an active role in the runtime functioning of the program. |
| * In case of a template, prefer use of typename keyword over class. |
| |
| [heading Specialisations and dispatching conventions] |
| |
| * Algorithms are free inline functions, taking any geometry. Parameters are often one or two geometries |
| * There might be an overload for a strategy. The strategy takes, a.o. care of coordinate systems |
| * The free `inline` function forwards to a dispatch struct, specialized for the geometry type (so for point, polygon, etc.) |
| * They have an `static` (`inline`) function called apply |
| * The dispatch struct calls, or is derived from, an struct implemented in namespace detail |
| * There the same: a `struct` with a `static` (`inline`) function called apply |
| * This way the implementation structs are building blocks, they can be reused |
| * In fact they are reused often by the multi-versions of the algorithms |
| |
| ``` |
| namespace boost { namespace geometry |
| { |
| |
| namespace detail { namespace foo |
| { |
| |
| template <typename Point> |
| struct foo_point |
| { |
| // template parameters here |
| static inline int apply(Point const& p) |
| { |
| // do something here |
| return 1; |
| } |
| }; |
| |
| }} // namespace detail::foo |
| |
| namespace dispatch |
| { |
| |
| template |
| < |
| Geometry, |
| Tag = typename geometry::tag<Geometry>::type |
| > |
| struct foo |
| { |
| }; |
| |
| // Specialization for POINT |
| ... |
| |
| } // namespace dispatch |
| |
| template <typename Point> |
| inline int foo(Point const& point) |
| { |
| return dispatch<Point>::apply(point); |
| } |
| |
| }} // namespace boost::geometry |
| ``` |
| |
| [heading Contributing code] |
| |
| * Create a patch, open a ticket in the Boost Trac with your patch attached. |
| * Alternatively, post your patch to the Boost.Geometry mailing list. |
| * If you contribute a code, always try to provide a minimal test for it. |
| |
| [endsect] |