wiki:BestPracticeHandbook

Version 4 (modified by Niall Douglas, 7 years ago) ( diff )

--

Links To Examples Of Best Practice For C++ 11/14 Libraries

originally written by Niall Douglas May 2015

As part of preparing my C++ Now 2015 presentation "A review of C++ 11/14 only Boost libraries" I examined ten C++ 11/14 mandatory libraries heading towards Boost which were:

Name Authors Min C++ Boost headers required Entered Boost peer review queue Description Repository
Boost.Fiber Oliver Kowalke 14 Context, Config Conditionally accepted a framework for micro-/userland-threads (fibers) scheduled cooperatively https://github.com/olk/boost-fiber
Boost.AFIO Niall Douglas, Paul Kirth 11 none 2013-10 strongly ordered portable asynchronous filesystem and file i/o extending ASIO https://github.com/BoostGSoC13/boost.afio
Boost.DI Krzysztof Jusiak 14 none 2015-01 provides compile time, macro free constructor dependency injection https://github.com/krzysztof-jusiak/di
Boost.Hana Louis Dionne 14 none 2015-04 functional programming in C++ based around transformations of heterogeneous collections of types. https://github.com/ldionne/hana
Boost.Http Vinícius dos Santos Oliveira 11 asio, filesystem, system, datetime, utility 2015-04 create applications that need to expose services through HTTP https://github.com/BoostGSoC14/boost.http
Boost.APIBind Niall Douglas 11 none not submitted yet toolkit for modularizing Boost libraries, managing versioned API and ABI dependency binds, makes it easy for Boost libraries to switch between use of the C++ 11 STL and the Boost STL https://github.com/ned14/Boost.BindLib
Boost.Expected Pierre Talbot, Vicente J. Botet Escriba 11 none not submitted yet category and functional programming in C++ based around the monadic expected<T, E> https://github.com/ptal/expected
Boost.Tick Paul Fultz II 11 none not submitted yet trait introspection and concept creator for C++11 https://github.com/pfultz2/Tick
Boost.Fit Paul Fultz II 11 none not submitted yet provides utilities for functions and function objects https://github.com/pfultz2/Fit
Boost.Sqlpp11 Roland Bock 11 none not submitted yet A type safe embedded domain specific language for SQL queries and results in C++ https://github.com/rbock/sqlpp11

There was very significant divergence in best practices between these libraries at the time of examination, and moreover the divergences were uneven possibly reflecting an uneven understanding of what best practice might be in C++ 11/14. Thence from my examination I have prepared the list below of what I felt were best practices in C++ 11/14 mandatory libraries with hyperlinks to the relevant source code files in the relevant libraries above. As what a "best practice" is or is not may vary according to opinion, I have attempted to provide a rationale for each of the suggestions below. It is up to library authors to weigh each suggestion and to decide whether to apply it, or not, to their library.

One will note that the list below is much more C++ 11/14 focused than Boost focused. This is because it is derived from the first crop of C++ 11/14 mandatory Boost libraries. This is not a handbook for writing Boost libraries or even C++ 11/14 Boost libraries, if you want that first start reading here (note some of the guidelines on that page don't really apply to C++ 11/14 libraries) and then read here and here.

I have tried to keep these points generic to all C++ 11/14 libraries in the hope that they are useful far outside Boost. I have also ordered them with what I consider the most important ("strongly consider") first and not as important ("consider") later.

1. Strongly consider using git and GitHub to host a copy of your library and its documentation

All the Boost libraries are on github, and all the free tooling exampled below integrates easily with github. Choosing github makes your life much easier. Note that as git is a distributed source code control system, you can keep a canonical master copy anywhere and write a script which autorefreshes the github copy, thus triggering any of the free tooling you have integrated there.

Github also provides free website hosting for HTML. Have a script automatically generate documentation and commit it to the gh-pages branch in your normal repo. This should present a copy of your HTML at http:// username.github.io/repository.

This is the script which generates the documentation for proposed Boost.AFIO, and indeed you can see the exact output generated by this script at http://boostgsoc13.github.io/boost.afio/. You may find it useful.

cd boost-local
rm -rf libs/afio/doc/doxy/doxygen_output/html
mkdir -p libs/afio/doc/doxy/doxygen_output/html
cd doc
../b2 -a ../libs/afio/doc
cd ../..
if [ ! -e publish ]; then
git clone -b gh-pages git@github.com:BoostGSoC13/boost.afio.git publish
fi
cd publish
git reset --hard b1414e11be50ff81124e2e1583f1bbb734ad9ead
cd ..
rm -rf publish/*
mkdir -p publish/doc/html
cp -a boost-local/doc/html/afio* publish/doc/html/
cp -a doc/src publish/doc/
cp -a doc/src/images/boost.png publish/
cp -af boost-local/doc/src publish/doc/
mkdir -p publish/libs/afio/doc
cp -a doc/* publish/libs/afio/doc/
cd boost-local/libs/afio/doc/doxy
doxygen
cd ../../../../../publish
cp -a ../boost-local/libs/afio/doc/doxy/doxygen_output/html .
cp -a ../Readme.md .
cp -a ../Readme.md Readme.html
echo '<html><head><title>Boost.AFIO documentation</title><meta http-equiv="refresh" content="300"/><body>
<h1>Boost.AFIO documentation</h1>
<p><a href="doc/html/afio.html">BoostBook format documentation</a></p>
<p><a href="html/index.html">Doxygen format documentation</a></p>
<p><a href="afio-stable.tar.bz2">Ready to go stable AFIO distribution with all git submodules (from master branch)</a></p>
<p></p>' > index.html
cat Readme.md | tail -n +4 >> index.html
echo '
</body></html>' >> index.html
git add .
git commit -a -m 'SHA stamp by Jenkins as building correctly' || true
git push -f

Some may wonder what the hard git reset to a SHA is for. This prevents the gh-pages branch continuously growing in storage by breaking history for the branch, and therefore making git clone times grow excessively. As the branch is purely for HTML publishing, breaking history like this is safe.

Other examples of libraries which use github for their documentation:

2. Very strongly consider versioning your library's namespace

3. Strong consider trying your library on Microsoft Visual Studio 2015

More than half the libraries reviewed had no support for Microsoft Visual Studio, and only supported GCC and clang. When the authors were asked why, in many cases it was simply assumed that MSVC didn't implement much C++ 11/14 and the authors hadn't attempted MSVC support.

This is in fact untrue. Here is a complete list of C++ 11/14 features which VS2015 does NOT support (everything else you can assume it supports, including a full and complete C++ 14 STL):

  • Expression SFINAE (there are workarounds. Note the STL "turns on" magic Expression SFINAE support for those parts of the STL requiring it, so any Expression SFINAE done by the STL for you works as expected).
  • Any serious constexpr use (try "#define constexpr" i.e. disable it completely. Most of the time your code will compile and work. Consider using a BOOST_CONSTEXPR macro thereafter). It is claimed by Microsoft that full C++ 11 constexpr conformance is present, but to be honest in my own code I don't find anything less than C++ 14 constexpr useful in practice.
  • No two phase lookup. Reordering decls to make the compiler look up in a way which doesn't produce non-conforming outcomes is a straightforward, if annoying, workaround.
  • MSVC's C99 support is still less than complete, but it's significantly more complete than before.
  • MSVC's preprocessor is still non-conforming, but it's less broken than it has ever been.
  • Variable templates.
  • Non-static data member initialisers for aggregates.

VS2015 is a very highly conforming C++ 11/14 compiler. It meets or exceeds clang 3.3 on every C++ feature. VS2015 even has some support for C++ 1z (C++ 17) matching clang 3.5. See http://blogs.msdn.com/b/vcblog/archive/2015/04/29/c-11-14-17-features-in-vs-2015-rc.aspx.

I am not claiming that you won't get surprises when you try getting MSVC to compile your code which you thought was standards compliant. MSVC is not an AST based compiler and uses heuristics to trigger partial AST compilation, and therefore has a unique processing model which exposes your assumptions about what you think or thought is valid C++. This is exactly why it is worthwhile getting your C++ 11/14 library working on MSVC because you will get a better quality, more standards conforming C++ library out of it.

4. Consider making it possible to use an XML outputting unit testing framework, even if not enabled by default

A very noticeable trend in C++ 11/14 mandatory Boost libraries is that less than half are able to use Boost.Test, and use alternative unit testing systems.

There are many very good reasons not to use Boost.Test, but there are few good reasons to not be able to use Boost.Test at all.

TODO IN PROGRESS

5. Consider not doing compiler feature detection yourself

Note: See TracWiki for help on using the wiki.