Boost logo

Boost :

Subject: [boost] [MPL] A Proposal
From: Bruno Dutra (brunocodutra_at_[hidden])
Date: 2016-02-28 18:17:28


Dear Community,

About a year ago today, there was a proliferation of threads [1][2][3] in
this mailing list concerning the future of Boost.MPL, or even whether it
had a future at all, and opinions diverged widely on the matter. Many have
expressed concerns about the fact Boost.MPL was long outdated and proposed
major changes to open path for modernization, while some others argued
against it, fearing unexpected and disastrous side-effects could propagate
throughout the rest of Boost. A few questioned if it was worth it at all to
spend any further resources on Boost.MPL given the fact new alternatives
were coming up, such as Boost.Hana, which departed entirely from template
metaprogramming, yet some argued TMP remained a competitive alternative for
type computations in C++14 as it has been demonstrated by Peter Dimov in
his impressive articles [4] on modern TMP.

Amidst all this, a proposal by Robert Ramey [5] caught my attention and
inspired me to develop what I call Metal [6], a template metaprogramming
library designed on the same core principles as Boost.MPL, but written from
the very beginning to take full advantage of C++11. Metal was not designed
to be a strict drop in replacement for Boost.MPL though, it was rather
meant to be regarded as a modern version of Boost.MPL's original API,
diverging only where it could really benefit from modern C++ and that
essentially means gains of several orders of magnitude in performance** and
lower memory consumption. At this point Metal is very close to where I
originally intended to bring it and I think it's time I gauge interest from
the community on a modest proposal I've been maturing along the past year.

As a modern approach to the same task that Boost.MPL was meant to address,
I don't believe Boost would benefit at all from yet another TMP library
that would essentially compete with Boost.MPL and even Boost.Hana in some
cases, specially as maintainers of older code that depends on Boost.MPL
would have to go through major refactoring efforts in order to benefit from
such an addition to Boost. I would like to propose something different
instead.

My proposal is to make Metal officially into a new revision of Boost.MPL's
API, essentially MPL2 as the original proposal by Robert Ramey put it,
merging both into one single TMP library. The idea would be to provide a
thin proxy for the current Boost.MPL API which would have two backends
configurable by preprocessor switches: the original implementation and a
another one based on Metal. This way older code using Boost.MPL could see
immediate gains on performance by selecting the newer backend on supported
compilers, while at the same time legacy code maintained on older compilers
could still rely on Boost.MPL's impressive ability to run virtually
anywhere. On the other hand, newer projects interested on pure type
computations would have the newer API entirely available to them.

This proposal also overcomes the problem of dealing with the
maintainability of Boost.MPL, since it provides a way for smooth transition
from legacy hacks required by ancient compilers into a cleaner and easier
to maintain C++11 codebase, besides avoiding any breaking changes within
existing code in the process. Furthermore, should this proposal make it
into Boost, I would be naturally willing to take responsibility for the
maintenance of Boost.MPL, which AFAIK has been maintained by the CMT for
quite some time now, often with limited resources.

Comparing Metal and Boost.MPL there are a few noteworthy differences.
Metafunction Classes have proven themselves entirely unnecessary and have
thus been removed altogether in favour of pure Lambdas (in the Boost.MPL
sense). Moreover, iterators make little sense in a functional world, so
these too have been removed despite the fact they may easily be emulated in
the new design. Moreover Metal develops the concept of optionals, that is,
its metafunctions only have a nested ::type defined when they may be
successfully computed, what may be safely tested using metal::is_just and
may also be used to SFINAE out of miscomputations.

Finally I'd like to point out that Metal was designed to be portable across
as many compilers as possible and three of the most popular ones are
continuously tested using Travis and Appveyor: Clang 3.5+, GCC 4.8+ and
MSVC 14 (2015).

I hope this is a reasonable proposal and I look forward into your opinions
about it.

** Even though I haven't published any benchmarks yet, an example follows
just to back my claims regarding performance (just tested on my personal
laptop running linux):

//Generate a list containing 10 thousand instances of
std::integral_constant, from 0 to 9999
using l = metal::enumerate_t<metal::integer<10000>>;

// GCC 5.3 ~0.4 s
// Clang 3.7 ~0.5 s

//Transform a list containing 5 thousand numbers by squaring each element
using l1 = metal::enumerate_t<metal::number<long long, 5000>>;
using l2 = metal::transform_t<metal::pow<metal::_1, metal::integer<2>>, l1>;

// GCC 5.3 ~5.6 s
// Clang 3.7 ~3.0 s

[1]: http://thread.gmane.org/gmane.comp.lib.boost.devel/257680
[2]: http://thread.gmane.org/gmane.comp.lib.boost.devel/257983
[3]: http://thread.gmane.org/gmane.comp.lib.boost.devel/258843
[4]: http://pdimov.com/cpp2/simple_cxx11_metaprogramming.html
[5]: http://rrsd.com/blincubator.com/bi_suggestion/mpl-lite-or-mpl2/
[6]: http://brunocodutra.github.io/metal/

Regards,
Bruno Dutra


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk