Version 4 (modified by 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.
-
Links To Examples Of Best Practice For C++ 11/14 Libraries
- 1. Strongly consider using git and GitHub to …
- 2. Very strongly consider versioning your library's namespace
- 3. Strong consider trying your library on Microsoft Visual Studio 2015
- 4. Consider making it possible to use an XML outputting unit testing …
- 5. Consider not doing compiler feature detection yourself
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:
- https://olk.github.io/libs/fiber/doc/html/
- https://boostgsoc13.github.io/boost.afio/
- https://krzysztof-jusiak.github.io/di/boost/libs/di/doc/html/
- https://boostgsoc14.github.io/boost.http/
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