only boost libraries a review of c++ 11/14...header only 1 1 0 boost.http vinícius dos santos...

Post on 07-Jul-2020

1 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

A review of C++ 11/14 only Boost libraries

Boost.Fiber Boost.AFIO Boost.DL Boost.APIBind

Niall Douglas

Contents:1. Libraries examined, and rationale for

excluding some and not others5. Boost.Fiber (provisionally approved)4. Boost.AFIO (review queue, Oct 2013)3. Boost.DL (review queue, Jan 2015)2. Boost.APIBind (née BindLib)6. Big picture answers - and why we need a

C++ 11/14 only modular Boost 2.0

C++ 11/14 only Libraries examined15 Libraries:● AFIO ****● BindLib (APIBind) ****● DI **● Dispatch● Expected ***● Fiber ***● Fit *

● Hana *● Http **● Proto ox● Range● SIMD● Spirit X3● Sqlpp11 *● Tick *

How close are these to entering Boost?

Library status as at March 2015Name AuthorsMin C++

Headers required

Entered peer review queue

Boost ready

source code

Boost ready unit

testing

Boost ready docs

Boost ready build

Uses Travis &

Appveyor

Uses valgrind

memcheckUses

coveralls

Boost.Fiber Oliver Kowalke 14Context, Config

Conditionally accepted 1 1 1 1 0 0 0

Boost.AFIO Niall Douglas, Paul Kirth

11 none 2013-10 1 1 1 header only 1 1 1

Boost.DI Krzysztof Jusiak 14 none 2015-01 1 0.9 1 1 1 1 1

Boost.Hana Louis Dionne 14 none 2015-04 1 0.9 0.6 header only 1 1 0

Boost.HttpVinícius dos Santos Oliveira

11asio, filesystem,

system, datetime, utility

2015-04 1 0.3 0.3 0 0 0 0

Boost.APIBind Niall Douglas 11 none 0 1 0.1 0 header only 0.5 1 1

Boost.ExpectedPierre Talbot, Vicente J. Botet Escriba

11 none 0 1 1 0.1 header only 0 0 0

Boost.Tick Paul Fultz II 11 none 0 0 0.9 0.9 header only 1 0 0

Boost.Fit Paul Fultz II 11 none 0 0 0.9 0.9 header only 1 0 0

Boost.Sqlpp11 Roland Bock 11 none 0 0 0.5 0.4 header only 1 0 0

And the others ...○ Proto 0x, Range, Spirit X3

○ Not approaching a Boost peer review yet I felt● Hana, Tick, Fit

○ Authors are presenting at this conference, no need to (badly) duplicate them …

● SIMD and Dispatch○ C++ 14 version reimplements 98 version without

many surprises● So this talk covers in this reversed order:

APIBind, AFIO, Fiber and DI

Boost.APIBind(still BindLib at time of writing)

Lead maintainer: Niall Douglas (me)

Boost.APIBind - what is it factual?

“toolkit for making Boost vs STL 11 dependency injectable”

“toolkit for versioning library APIs and ABIs”“toolkit for hard version API binds rather than

‘whatever available’ API version”“toolkit for explicitly encoding dependencies

between libraries”

Boost.APIBind - what is it philosophically?

“toolkit for enabling a Boost library to be optionally standalone from Boost i.e. modular

Boost made real”Requires: No Boost dependencies (obviously)Min >= Compilers: Any C++ 98Max >= Compilers: clang 3.2, GCC 4.7, VS2013** VS2013 doesn’t support API/ABI versioning due to lack of inline namespace support in the compiler.

Parts

Boost.APIBind - parts 1/3● Absolute minimal Boost emulation headers

<boost/config.hpp><boost/test/unit_test.hpp>

● cpp_feature.hProvides consistent SG-10 compiler feature checking macros for all compilers

● import.hPreprocessor macros easing loose coupling

Boost.APIBind - parts 2/3

● Incomplete STL11 binds for array, atomic, chrono, condition_variable, functional, future, mutex, random, ratio, regex, system_error, thread, tuple, type_traits, typeindex○ Can bind to either the STL or Boost

● Incomplete STL1z binds for filesystem, networking○ Can bind to the STL (Dinkumware), Boost, or

standalone ASIO the Networking TS reference impl

Boost.APIBind - parts 3/3● A python script for helping autogenerate

macro boilerplate for ABI signature generation

● libclang AST parsing tool which converts library header files into API binds○ This is used to break up legacy monolithic

namespaces into modular rebindable parts○ Any library in its own namespace doesn’t need this

Layer 1: Versioning API and ABI

Enabling your library to coexist with itself using the C preprocessor, inline namespaces, and namespace

aliasing

Boost.APIBind - macros from import.h

● BOOST_BINDLIB_NAMESPACE(sig)● BOOST_BINDLIB_NAMESPACE_BEGIN

(sig)● BOOST_BINDLIB_NAMESPACE_END(sig)● BOOST_BINDLIB_INCLUDE_STL11

(prefix, impl, lib)● BOOST_BINDLIB_INCLUDE_STL1z

(prefix, impl, lib)

Boost.APIBind - version signatures

#define BOOST_AFIO_V1(boost), (afio), (v1, inline)#define BOOST_AFIO_V1_NAMESPACEBOOST_BINDLIB_NAMESPACE(BOOST_AFIO_V1)#define BOOST_AFIO_V1_NAMESPACE_BEGIN BOOST_BINDLIB_NAMESPACE_BEGIN(BOOST_AFIO_V1)#define BOOST_AFIO_V1_NAMESPACE_END BOOST_BINDLIB_NAMESPACE_END(BOOST_AFIO_V1)

Boost.APIBind - in your libraryTraditional:namespace boost { namespace afio { struct foo; } }

boost::afio::foo;

APIBind:BOOST_AFIO_V1_NAMESPACE_BEGINstruct foo;BOOST_AFIO_V1_NAMESPACE_ENDBOOST_AFIO_V1_NAMESPACE::foo

Boost.APIBind - use of your library 1/3

I want to use latest AFIO in mylib please:#include <boost/afio/afio.hpp>namespace mylib { namespace afio = boost::afio;}

The inline namespacing hides the real namespace. Latest AFIO version therefore always appears at boost::afio.

Boost.APIBind - use of your library 2/3

I want to use specifically only v1 of AFIO in mylib please:

#include <boost/afio/afio_v1.hpp>namespace mylib { namespace afio = BOOST_AFIO_V1_NAMESPACE;}

Boost.APIBind - use of your library 3/3

namespace boost { namespace afio { namespace v1 { … } // legacy inline namespace v2 { … } // latest} }#include <boost/a> // uses AFIO v1. Works!#include <boost/b> // uses AFIO v2. Works!boost::afio::foo; // Finds latest (v2)BOOST_AFIO_V1_NAMESPACE::foo; // v1

Layer 2: Dependency Injection of which STL to use per version of your

libraryEnabling any user specified configuration of your

library to coexist with itself

Boost.APIBind - Multi ABI 1/8● What if you would like your library to use

either Boost.Thread or the STL 11 Thread?● What if you would like your library to use

either Boost.Filesystem or the STL 1z Filesystem TS?

● What if you would like your library to use either Boost.ASIO or the STL 1z Networking TS?

Boost.APIBind - Multi ABI 2/8

What if header only library A is dependent on Boost.AFIO v1 configured with Boost.Thread, Boost.Filesystem and Boost.ASIOBUTHeader only library B is dependent on Boost.AFIO v1 configured with STL 11 Thread, STL 1z Filesystem and STL 1z Networking?

Boost.APIBind - Multi ABI 3/8This problem is highly likely in future Boost libraries● Only Boost.ASIO and Boost.AFIO currently

let external code dependency inject Boost OR STL11

● Of the five libraries in the review queue, three only use STL11 and one only uses Boost - this is a big future problem to fix

Boost.APIBind - Multi ABI 4/8

1. Decide on user set macros for each ABI config option:○ BOOST_AFIO_USE_BOOST_THREAD = 0|1○ BOOST_AFIO_USE_BOOST_FILESYSTEM = 0|1○ ASIO_STANDALONE = 0|1

2. Have config.hpp convert those into:○ BOOST_AFIO_V1_STL11_IMPL = std|boost○ BOOST_AFIO_V1_FILESYSTEM_IMPL = std|boost○ BOOST_AFIO_V1_ASIO_IMPL = asio|boost

Boost.APIBind - Multi ABI 5/8

3. Instead of#define BOOST_AFIO_V1 (boost), (afio), (v1, inline)

do:#define BOOST_AFIO_V1 (boost), (afio), (BOOST_BINDLIB_NAMESPACE_VERSION(v1, BOOST_AFIO_V1_STL11_IMPL, BOOST_AFIO_V1_FILESYSTEM_IMPL, BOOST_AFIO_V1_ASIO_IMPL), inline)

Boost.APIBind - Multi ABI 6/8

4. Call gen_guard_matrix.py with the user settable ABI config macros:

./gen_guard_matrix.py BOOST_AFIO_NEED_DEFINE BOOST_AFIO_USE_BOOST_THREAD BOOST_AFIO_USE_BOOST_FILESYSTEM ASIO_STANDALONE

#undef BOOST_AFIO_NEED_DEFINE

#if !BOOST_AFIO_USE_BOOST_THREAD && !BOOST_AFIO_USE_BOOST_FILESYSTEM && !ASIO_STANDALONE# ifndef BOOST_AFIO_NEED_DEFINE_000# define BOOST_AFIO_NEED_DEFINE_000# define BOOST_AFIO_NEED_DEFINE 1# endif

#elif BOOST_AFIO_USE_BOOST_THREAD && !BOOST_AFIO_USE_BOOST_FILESYSTEM && !ASIO_STANDALONE# ifndef BOOST_AFIO_NEED_DEFINE_100# define BOOST_AFIO_NEED_DEFINE_100# define BOOST_AFIO_NEED_DEFINE 1# endif

#elif !BOOST_AFIO_USE_BOOST_THREAD && BOOST_AFIO_USE_BOOST_FILESYSTEM && !ASIO_STANDALONE

Boost.APIBind - Multi ABI 7/8

5. Remove header guards in your header file:

#ifndef SOME_GUARD_MACRO_HPP#define SOME_GUARD_MACRO_HPP... #endif

Boost.APIBind - Multi ABI 8/8

6. Replace with new header guards:

#include "config.hpp"#ifdef BOOST_AFIO_NEED_DEFINEBOOST_AFIO_V1_NAMESPACE_BEGIN...BOOST_AFIO_V1_NAMESPACE_END#endif

Ugh that’s dirty! Recommending non-standard header guards in all future Boost libraries? I don’t like it! (P.S. Neither do I!)

But how is it for users to use these libraries?

// test_all_multiabi.cpp in the AFIO unit tests

// A copy of AFIO + unit tests completely standalone apart from Boost.Filesystem#define BOOST_AFIO_USE_BOOST_THREAD 0#define BOOST_AFIO_USE_BOOST_FILESYSTEM 1#define ASIO_STANDALONE 1#include "test_all.cpp"#undef BOOST_AFIO_USE_BOOST_THREAD#undef BOOST_AFIO_USE_BOOST_FILESYSTEM#undef ASIO_STANDALONE

// A copy of AFIO + unit tests using Boost.Thread, Boost.Filesystem and Boost.ASIO#define BOOST_AFIO_USE_BOOST_THREAD 1#define BOOST_AFIO_USE_BOOST_FILESYSTEM 1// ASIO_STANDALONE undefined#include "test_all.cpp"#undef BOOST_AFIO_USE_BOOST_THREAD#undef BOOST_AFIO_USE_BOOST_FILESYSTEM

Boost.APIBind - Quick Summary

● What I just explained looks dirty, messy and brittle, but it actually is fairly trouble free in practice and it works○ The config.hpp preprocessor boilerplate is easily

templated and is fire and forget installable○ Only real sore point is it’s too easy to break

multiabi, but unit testing catches that immediately and that isn’t the fault of the APIBind technique

○ And this solution is FAR simpler than ASIO’s method

How do binds modularise and dependency inject a

legacy monolithic namespace like std or

boost?Symbolic linking between C++ namespaces

Boost.APIBind - quick reminder

● Incomplete STL11 binds for array, atomic, chrono, condition_variable, functional, future, mutex, random, ratio, regex, system_error, thread, tuple, type_traits, typeindex○ Can bind to either the STL or Boost

● Incomplete STL1z binds for filesystem, networking○ Can bind to the STL (Dinkumware), Boost, or

standalone ASIO the Networking TS reference impl

Boost.APIBind - how binds work 1/5

1. EXPORT: Feed your interface (header) file to the libclang tool and it spits out a bind for each of the following matching a regex:○ Types (struct, class) and functions.○ Template types (including template templates),

and template functions.○ enums (scoped and C form).○ Currently missing: default template args, variables

and template variables.

In <ratio> header file:

namespace std { template <intmax_t N, intmax_t D = 1> class ratio; }

We invoke:

./genmap bind/stl11/std/ratio BOOST_STL11_RATIO_MAP_ "std::([^_][^:]*)" ratio "boost::([^_][^:]*)" boost/ratio.hppBind generated by tool:

BOOST_STL11_RATIO_MAP_NAMESPACE_BEGIN#ifdef BOOST_STL11_RATIO_MAP_NO_RATIO

#undef BOOST_STL11_RATIO_MAP_NO_RATIO

#else

template<intmax_t _0, intmax_t _1> using ratio = ::std::ratio<_0, _1>;#endif

BOOST_STL11_RATIO_MAP_NAMESPACE_END

2. IMPORT: Into your config.hpp file add this:#define BOOST_STL11_RATIO_MAP_NAMESPACE_BEGIN namespace mylib {

#define BOOST_STL11_RATIO_MAP_NAMESPACE_END }

// Bind std::ratio into namespace mylib

#include BOOST_BINDLIB_INCLUDE_STL11(bindlib, std, ratio)

// OR Bind boost::ratio into namespace mylib

#include BOOST_BINDLIB_INCLUDE_STL11(bindlib, boost, ratio)

Expands into:#include “bindlib/bind/stl11/std/ratio”

Equals the effect of symbolically linking std::ratio into mylib namespace:

namespace mylib { template<intmax_t _0, intmax_t _1> using ratio = ::std::ratio<_0, _1>; }

Boost.APIBind - how binds work 4/53. USE: No longer qualify use of ratio<Num,

Den> when in namespace mylib

namespace mylib {

// From auto generated bind #include file in config.hpp

template<intmax_t _0, intmax_t _1> using ratio = ::std::ratio<_0, _1>;

// In rest of codebase

std::ratio<1, 2> foo; // Use naked!

}

Boost.APIBind - how binds work 5/5What have we just achieved?

“C preprocessor controlled dependency injection of part of a monolithic legacy C++

namespace A into client namespace B”● The C preprocessor can now select what the

mylib::ratio<Num, Den> symbolic link points to:○ mylib::ratio<N, D> => std::ratio<N, D>

Notes on porting a Boost library to Boost.APIBind

My experiences porting Boost.AFIO to APIBind

Boost.APIBind - Porting a Boost library 1/5

● Despite the minimal Boost emulations provided by APIBind, this IS the same effort as porting your Boost library to a whole new platform

● Regular expression find & replace in files + regular git commits is going to be your best friend … but a slog!

● PLAN whether you’ll make use of a STL11 feature dependency injected:○ BAD IDEA: shared_ptr<>, is_constructible<> etc○ GOOD IDEA: thread, filesystem, networking

Boost.APIBind - Porting a Boost library 2/5

● Remember you don’t HAVE to make Boost STL vs STL11 dependency injected; don’t HAVE to implement multi-abi; don’t HAVE to … etc - all this reduces the porting effort needed○ AND you can do a port incrementally!

● Here are my experiences porting Boost.AFIO to BindLib ...

Boost.APIBind - Porting a Boost library 3/5

● AFIO is about 8k lines of library, but 18k lines including all unit testing - so small

● Approx. 60 hours to port AFIO over to BindLib - mostly tedious find & replace

● Found dozens of unexpected bugs like ABI leakage or incorrect use of STL11 or bad assumptions in unit testing

Boost.APIBind - Porting a Boost library 4/5

● Very significantly improved rigour of code quality - this was unexpected at beginning - specifying dependencies is good!

● Benefits gained is that AFIO is now very configurable and flexible for end users○ Users download a single header only tarball or add

AFIO to their git repo as a git submodule andthey’re ready to go

Boost.APIBind - Porting a Boost library 5/5

○ In fact most new AFIO development work exclusively uses the standalone edition - I’ve seen very significant productivity improvements not dealing with the slow Boost.Build et al and using a precompiled header as an AFIO “C++ module”

○ Still needs Boost for docs generation○ Using APIBind as the foundation for a C++ 11 only

Boost 2.0 is definitely a valid vision … (c.f. Robert’s talk, also this conference)

Questions?

Boost.AFIOLead maintainer: Niall Douglas (me)

Boost.AFIO - what is it?“strongly ordered portable asynchronous filesystem and file i/o extending ASIO”

Requires: Filesystem TS, Networking TS>= Compilers*: clang 3.2, GCC 4.7, VS2013>= OSs*: Microsoft Windows XP, Linux 2.6.32, Android, FreeBSD 10, OS X 10.5

* All these are per-commit CI tested, though not necessarily the earliest supported version. Only Microsoft Windows currently has a native asynchronous backend.

Boost.AFIO vs Boost.ASIO 1/2● AFIO uses continuable futures instead of asio::

async_result. Why deviate from ASIO?○ For file i/o you want strong always-forward

ordering across all operations, for network i/o ordering isn’t as important

○ A file i/o has enormous latency variance, far more than networking

○ A file i/o takes far longer than a network i/o so overheads of a future-promise aren’t so important

○ Monadic control flow and error handling makes a lot of sense with file i/o

Boost.AFIO vs Boost.ASIO 2/2● The use case for async file i/o is VERY different to

network i/o○ Async file i/o is usually slower (warm cache ~15%)

than sync file i/o■ You choose async for control not performance

○ Predictability is much more important for file i/o■ Avoiding file system race conditions■ Identical semantics on Windows and POSIX■ Coping well with networked file systems■ NOT LOSING DATA!

Parts

Boost.AFIO - parts 1/3● A thread source capable of executing

closures○ defaults to an ASIO io_service with eight kernel

threads○ each closure consumes and returns a future file

handle (futures can also return exceptions of course)

○ once used std::packaged_task, now uses enqueued_task which is an intrusive implementation for improved performance

Boost.AFIO - parts 2/3

● A path class thinly wrapping std::filesystem::path○ Main difference is on Windows where it converts to

a NT kernel path, not Win32 path● Universal stat_t and statfs_t

○ Thanks to using NT kernel API directly achieves a very close equivalence to POSIX

● A file handle, async_io_handle

Boost.AFIO - parts 3/3

● A dispatcher, async_io_dispatcher○ takes in some thread source○ applies default flags to operations (e.g. always

fsync on file close) to save doing that per op○ accepts batches of operations to schedule○ issues operations according to dependency chain○ only serialises execution twice per operation○ just eight mallocs and frees per operation○ Average 15 μs latency ± 0.15 μs @ 95% C.I.

Boost.AFIO - supported operations● Filing system race guarantees per operation● Batch async create/open/delete dirs, files and

symlinks● Batch async fsync, truncate, scatter/gather read/write● Batch async enumeration of directories, filing systems

and file extents● Batch async hole punching/deallocation of file storage● Per-handle current path retrieval, metadata retrieval,

hard linking, unlinking and atomic relinking● Portable lock files (and soon portable file locking)

Importance to C++

Boost.AFIO - what C++ 11/14 does it use?

Not much due to supporting COM/C bindings:● C++ 11 up to what VS2013 implements

○ Makes use of some C++ 14 internally if available● Rvalue reference support (absolutely

essential due to the batch API)● Variadic templates (since v1.3)● Template aliasing (since v1.3, for APIBind

only)

Boost.AFIO - WG21 relevance● Intended to extend the Networking TS with

async file i/o for the C++ standard library● Intended to superset the Filesystem TS with

race guaranteed filesystem operations● Intended to seamlessly integrate with

resumable functions in a future STL○ i.e. you write C++ synchronously, but it executes

asynchronously

Questions?

Boost.FiberLead maintainer: Oliver Kowalke

Boost.Fiber - what is it?

“a framework for micro-/userland-threads (fibers) scheduled cooperatively”

Requires: Boost.Context, Boost.Config>= Compilers: clang 3.4, GCC 4.9 (C++ 14)>= OSs: Microsoft Windows (Mingw), POSIX>= CPUs: ARM, x86, MIPS, PPC, SPARC, x64

Boost.Fiber - what is it?Its main use case is simplification of async implementation logic for end users:● With futures you might monadically do: write(buffer1).

then([](auto f) { return f ? write(buffer2) : f; }).then(read(buffer3)).get();

● With Fibers:if(write(buffer1).get()) write(buffer2).get();read(buffer3).get();

Parts

Boost.Fiber - parts● A fiber is a user space cooperatively

scheduled thread○ Stackful context switching (Boost.Context) + a

scheduler○ Currently about 10x faster than kernel threads

● Fibers execute thread locally○ If one Fiber blocks on something e.g. a fiber::

future, only other fibers in the same thread may execute during the wait

Boost.Fiber - parts

● A fiber based replica of the STL threading primitivesstd::thread => fiber::fiberstd::this_thread => fiber::this_fiberstd::mutex => fiber::mutexstd::condition_variable => fiber::condition_variablestd::future<T> => fiber::future<T>

Importance to C++

Boost.Fiber - what C++ 11/14 does it use?● C++ 14 only mainly due to use of

execution_context in Boost.Context and deferred parameter pack expansion○ That in turns makes use of move capturing lambdas

and std::integer_sequence○ Requiring 14 saves a lot of workaround work though

● Probably could support VS2015 without too much work - VS2015 only lacks generalised constexpr

Boost.Fiber - WG21 relevance● A debate currently exists in WG21 between compiler-

generated resumable functions (N4134) and “barebones only” minimal standardised coroutine support for library frameworks to build upon○ Debate summarised in N4232 (Stackful Coroutines and Stackless

Resumable Functions)

● I am personally torn between the two approaches○ I dislike the viral keyword markup “island” in N4134○ But I accept only the compiler can automate many

optimisations e.g. fixedstack call tree leaf slicing

Questions?

Boost.DILead maintainer: Krzysztof Jusiak

Boost.DI - what is it?“provides compile time, macro free constructor dependency injection”

Requires: No Boost dependencies>= Compilers: clang 3.4, GCC 4.9, VS2015 (C++ 14)>= OSs: Microsoft Windows, POSIX

Boost.DI - what is it?What is dependency injection?● Well known design pattern in Web 2.0

service design and .NET● As implied above, generally associated with

dynamic language runtimes, not static ones like that of C++

● Yet C++ actually has a very close analogue to DI in template metaprogramming ...

Boost.DI - what is it?template <typename OutputPolicy, typename LanguagePolicy>class HelloWorld : private OutputPolicy, private LanguagePolicy{ …

typedef HelloWorld<OutputPolicyWriteToCout, LanguagePolicyEnglish> HelloWorldEnglish;HelloWorldEnglish hello_world;hello_world.run(); // prints "Hello, World!"

typedef HelloWorld<OutputPolicyWriteToCout, LanguagePolicyGerman> HelloWorldGerman; HelloWorldGerman hello_world2;hello_world2.run(); // prints "Hallo Welt!"

Source: https://en.wikipedia.org/wiki/Policy-based_design

Boost.DI - what is it?DI is exactly the same design pattern as template policy mix-in instantiation:● Except it’s done at runtime, not during compile-time● This effectively makes Boost.DI an inverted plugin or

modular framework● Extremely useful for mocking, even for comprehensive

std::bad_alloc testing● It is surprising Boost doesn’t have a library

implementing this (the Strategy Pattern) before now

Parts

Boost.DI - parts● Metaprogramming framework to assemble

the appropriate make_unique<T> and make_shared<T> instances for some runtime specified dependency graph

● A registry of components and their relations● Ecosystem of related useful utilities e.g.

parser for XML config files which configure a dependency injection

Importance to C++

Boost.DI - what C++ 11/14 does it use?

● Makes heavy use of variadic templates, generic lambdas, constexpr, concept checking

● Nevertheless I can imagine this library written in 03 without drastic API changes○ The biggest pain would be that client code would

need to use Boost.Preprocessor to emulate variadic template overrides

Boost.DI - WG21 relevance

None that I am aware of

Questions?

Big Picture Answers

Why do these libraries require C++ 11 or 14? From an API perspectivePractical in C++ 03:1. Fiber only recently was an 03 library2. AFIO’s design really only needs rvalue refs

○ Without those it would look more C array-like to implement a batch API

3. DI’s design really only need variadic templates for its API to be clean

4. Http could just as easily be 03 only

Why do these libraries require C++ 11 or 14? From an API perspectiveImpractical in C++ 03:1. Hana simply isn’t possible without C++ 14

○ Pushes C++ 14 implementations to their limits2. Expected makes no sense without C++11

○ Monadic idiom makes no sense in C++ without rvalue refs, unrestricted unions and constexpr

3. Tick and Fit wouldn’t have much utility without C++ 11/14○ Concepts and traits are hard without constexpr

Is there a common theme of the most popular C++ 11/14 features used?Universally used:● Rvalue refs, lambdas, type inference,

variadic templates, static_assert, range for, long long, defaulted and deleted functions, nullptr, STL11, generic lambdas

Somewhat used:● Initializer lists, uniform initialisation,

constexpr, class enums, overrides & final

Is there a common theme of the most popular C++ 11/14 features used?

Not common:● Template aliases, unrestricted unions, new

literals, alignment, variable templates, member initializers, inline namespaces

Never seen used not even once:● Extern templates

Is there a common theme in choice of library design and use of third party libraries?

● Everybody avoids Boost.Test○ assert()/static_assert() is surprisingly common

● Most avoid Boost.Build in favour of cmake○ Usually header only with tests using only cmake, or

also cmake● Almost everybody tries to use as little Boost

as possible○ To the point of no Boost dependencies at all

Do these new libraries take notice of one another and integrate themselves well with other libraries, or are they ivory towers?

● Only AFIO presently provides a large number of build config options○ And all of those are STL selection options

● All the libraries reviewed are ivory towers○ Best traditions of early DIY pre-Boost!

● Indeed, all the libraries in the front matrix were also ivory towers○ Good rationale for a Boost 2.0 common library

How many of these forthcoming libraries explicitly seek to contribute to future C++ standardization?

Yes:● Fiber (async)● AFIO (async)● Hana (functional)● Expected

(functional)● Range (functional)

No:● DI● Http● APIBind● Tick● Fit

Are there techniques used in one library which would make a lot of sense to be used in another library, but for some reason are not?● Overwhelmingly yes!

○ Best Practice of C++ 11/14 is highly uneven across libraries

○ So much so I went ahead and wrote up a Handbook of Examples of Best Practices in C++ 11/14 libraries based on the ten libraries I reviewed for this talk

● This Handbook of Example implementations is now online (link at end of these slides) and its table of contents is ...

Best C++ 11/14 Practices Handbook

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

2. Strongly consider versioning your library's namespace using inline namespaces and requesting users to alias a versioned namespace instead of using it directly

3. Strongly consider trying your library on Microsoft Visual Studio 20154. Strongly consider using free CI per-commit testing, even if you have a

private CI5. Strongly consider per-commit compiling your code with static analysis

tools6. Strongly consider running a per-commit pass of your unit tests under both

valgrind and the runtime sanitisers

Best C++ 11/14 Practices Handbook

7. Strongly consider a nightly or weekly input fuzz automated test if your library is able to accept untrusted input

8. (Strongly) consider using constexpr semantic wrapper transport types to return states from functions

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

10. Consider breaking up your testing into per-commit CI testing, 24 hour soak testing, and parameter fuzz testing

11. Consider not doing compiler feature detection yourself12. Consider having Travis send your unit test code coverage results to

Coveralls.io

Best C++ 11/14 Practices Handbook

13. Consider creating a status dashboard for your library with everything you need to know shown in one place

14. Consider making (more) use of ADL C++ namespace composure as a design pattern

15. Consider defaulting to header only, but actively manage facilities for reducing build times

16. Consider allowing your library users to dependency inject your dependencies on other libraries

17. Consider being C++ resumable function ready18. Essay about wisdom of defaulting to standalone capable (Boost) C++

11/14 libraries with no external dependencies19. Essay about wisdom of dependency package managers in C++ 11/14

Anything else?● Boost which was sickly only a few years ago

is now in rude health● Seventeen new libraries since 2013 (9

passed review)● C++ 11/14 libs look like pre-Boost libs did

○ Obvious rationale for a C++ 11 only Boost 2.0 to repeat the Boost success, but with C++ 11/14■ I personally think that makes a C++ 11 only fully

modular Boost 2.0 highly wise

Thank youAnd let the discussions begin!

Link to Best C++ 11/14 Practices Handbook:https://svn.boost.

org/trac/boost/wiki/BestPracticeHandbook

top related