Boost logo

Boost :

Subject: Re: [boost] MPL and MPL core
From: Bruno Dutra (brunocodutra_at_[hidden])
Date: 2015-03-30 20:01:22


On Mar 29, 2015 2:40 PM, "Robert Ramey" <ramey_at_[hidden]> wrote:
> I've had occasion to think about this lately. How about this for an idea:
>
> Create two new libraries:
>
> MetaFunction - would contain the current content of mpl/metafunctions.
>
> Typelists - would contain the current content for mpl/sequences without the
> iterator functionality.
>
> Notes:
>
> In order to produce a simpler implementation they would not need to be
> backward compatible
> with compilers prior to C++11 (or 14 or ...)
>
> I don't think they would need the whole sections of integral constant.
>
> When the implementation can be done in terms of standard library components
> or with
> boost components - standard library components would be preferred.
>
> The ultimate goal is that these libraries would be attractive for
> incorporation into the
> standard library to complement type_traits and other stuff which has been
> taken from boost.
>
> There is already a lot of "raw material" such as the current mpl, eric's
> meta, lorises mpl11, and maybe some other stuff. Most of the documentation
> and tests could almost be transcribed from the current mpl. So it would be
> an "easy" job.
>
> Focus would be not on creating every more powerful functional programming
> tools and abstractions, but rather as set of simple, understandable tools
> which would make template meta programming more accessible to those of us
> who occasionally need it but can't spend a lifetime on it. Call it TMP for
> the rest of us.
>
> I've split it two pieces because I think that these are two orthogonal ideas
> and it's much easier to do two smaller things than it is one bigger think.
> I would expect typelists to depend upon metafunctions.
>
> I very much like the new names because I think they better clearly describe
> what they are.
>
> Of course current MPL would e around "forever" but it's usage in newer code
> would be discouraged.
>
> Robert Ramey

Since the recent discussions regarding MPL and ultimately
metaprogramming support in boost, I've engaged in an experimental
project, which I believe is close to what you are proposing, I call it
MPL2¹. I've been actually inspired by your Library Idea² at Boost
Incubator, so my main goal is to start from scratch and provide a drop
in replacement for current MPL.

I'm following 3 basic premises:

1. Compatibility shall be restricted to "modern compilers", that is,
if a compiler can't handle partial template specializations, template
template parameters, non type template parameters or other such basic
language features, then it can't handle MPL2.

2. It shall be "C++11 aware", that is, it shall not only take full
advantage of C++11 additions, especially variadic templates and
template aliases, but also fully support it.

3. It shall be able to replace the original MPL on any existing code
without modifications, provided it is compiled on a "modern compiler"
in the sense of premise #1.

Premise #1 addresses concerns that have been raised regarding the
maintainability of MPL, which is seriously handicapped by the various
tricky workarounds it was forced to ship back in the day in order to
guarantee compatibility over a wide range of [nowadays rather
obsolete] compilers. MPL2 is expected to be much easier to maintain
and improve.

Backwards compatibility will be provided by a separate include tree
which mimics that of current MPL and effectively translates MPL
constructs to MPL2 equivalents. In most cases it should boils down to
simply exposing constructs of namespace mpl2 to namespace mpl through
the "using" directive, but some room shall be granted for MPL2 to
diverge from MPL whenever it proves useful, provided, of course, a
proper translation be available at the legacy interface. It should be
noted, however, that this legacy interface is expected to "just work"
and nothing more, that is, no extra effort will be taken to guarantee
performance or widespread compatibility. Hence it should serve simply
as a natural bridge for any library, whose developers are willing to
update to MPL2

I'm also tentatively maintaining compatibility to C++98/03 despite
being advised otherwise by some experienced developers and so far it
is going surprisingly well. To accomplish that I came up with a very
simple and comprehensible set of macros³ which provide forward
compatibility of variadic templates, template aliases and some other
C++11 goodies to C++98/03 through what I call "semantic emulation".
All that without impairing code clarity or maintainability too much,
but that's of course just my opinion. I invite anyone interested to
take a look at it (links at the bottom) and perhaps share some
thoughts. I must also add that, whenever choices must be made,
C++11/14 is never chosen to be handicapped in favor of C++98/03, that
is, just like backwards compatibility to MPL, backwards compatibility
to older standards should merely work, solely for the sake of minimal
portability.

Furthermore, I've bought the idea that metafunctions are rather
dissociated from containers, so I've split the include tree into two
main trunks, currently called core, containing general metafunctions,
and sequences for the rest.

Now onto some MPL features I plan to improve on MPL2:

1. MPL is rather eager and mostly requires metafunctions to be
explicitly instantiated by the "[typename] <>::type" idiom, which I
find rather verbose and cumbersome. I do believe, peeking at the code,
that this design was more a necessity to maintain compatibility with
defective compilers than a planed feature. MPL2, on the other hand
should be mostly lazy, that is, for instance,
mpl2::pop_front<mpl2::list<int, float> > *is* a list just the same as
mpl2::list<float> or mpl2::pop_front<mpl2::list<int, float> >::type.
The latter, however, shall add functionality which is also not
available at MPL and this brings me to the second improvement.

2. Some "well behaved" containers, such as lists, shall have their
type specified in a way that template matching shall be possible,
essentially making iterators obsolete, like so:

//untested code, please don't be too picky c:

template<typename list>
struct grand_total;

template<typename h, typename... t>
struct grand_total<mpl2::list<h, t...> > :
    mpl2::plus<h, grand_total<typename mpl2::pop_front<mpl2::list<h,
t...> >::type> //mpl2::list<t...> works too, of course, but hey,
that's just an example

{};

template<typename h, typename... t>
struct grand_total<mpl2::list<> > :
    mpl2::int_<0>
{};

This, however, obviously requires metafunctions to be explicitly
instantiated, as may be noted on the example above, but that just
brings us back to what MPL is already. It won't be available for every
container though, for it makes it impossible to honor constant time
insertion at both ends of bidirectional containers, like
MPL::vector<>. Still a great number (majority perhaps?) of use cases,
which need only constant time insertion at one end should benefit of
it.

Finally I must add development is still at the very beginning and the
resources available to me, essentially time, is rather scarce, but I'm
seriously committed to bringing it about, so please don't give up on
me :)

Bruno Dutra

¹ https://github.com/brunocodutra/mpl2/tree/core
² http://rrsd.com/blincubator.com/bi_suggestion/mpl-lite-or-mpl2/
³ https://github.com/brunocodutra/mpl2/tree/core/include/boost/mpl2/core/compat


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