Boost logo

Boost :

Subject: Re: [boost] [GSoC][MPL11] Post C++Now update
From: Louis Dionne (ldionne.2_at_[hidden])
Date: 2014-05-19 13:28:23


Joel de Guzman <djowel <at> gmail.com> writes:

>
> On 5/19/14, 4:41 AM, Louis Dionne wrote:
> > After discussing the issue several times during the week, I (and others)
> > think it might be possible to merge Fusion and the MPL into a single
> > library. I am currently trying to write a library that does that. Since
> > this constitutes a large reorientation, I created a new repository which
> > is available at [2]. Those with interest should consider subscribing to
> > the repository to be updated as I make progress.
>
> Been there tried that...
>
> This has been proposed several times in the past. I reiterate my
> position: MPL and Fusion are different beasts and it is not good for
> both to be merged (if it is at all possible). MPL does not have the
> runtime components that Fusion needs and Fusion has runtime
> components that MPL *does not* need.

This is true, the MPL does not _need_ a runtime component. Adding one should
be harmless if done correctly. There might be a performance penalty though,
but I'll benchmark that eventually.

> Also, because of the runtime aspects of Fusion, the semantics of
> algorithms do not make sense in MPL. Take the any algo for example:
>
> http://tinyurl.com/mk2whdo
>
> Note that odd in that example is a runtime operation. How do you
> unite that? It works only with fusion sequences (with values)
> and not with MPL sequences (with types). In MPL, that would be a
> type-only predicate.

As of writing this, here is what I am able to do [1]:

Purely runtime predicate
------------------------
    struct odd {
        template <typename T>
        bool operator()(T t) const { return t % 2; }
    };

    assert(any(odd{}, list(1, 2)));
    assert(!any(odd{}, list(2, 4)));

Constexpr predicate
-------------------
    struct odd {
        template <typename T>
        constexpr bool operator()(T t) const { return t % 2; }
    };

    static_assert(any(odd{}, list(1, 2)), "");
    static_assert(!any(odd{}, list(2, 4)), "");

Type-only predicate
-------------------
    struct odd {
        template <typename T>
        constexpr auto operator()(T t) const { return t % int_<2>; }
    };

    static_assert(std::is_same<
        decltype(any(odd{}, list(int_<1>, int_<2>))),
        Bool<true>
>::value, "");

    static_assert(std::is_same<
        decltype(any(odd{}, list(int_<2>, int_<4>))),
        Bool<false>
>::value, "");

The trick for the type-only predicate is that there exists an overload

    template <int i, int j>
    constexpr Int<i % j> operator%(Int<i>, Int<j>) { return {}; }

where Int<...> is the type of int_<...>. Since int_<...> is implicitly
constexpr convertible to int, one can just write the predicate as

    struct odd {
        template <typename T>
        constexpr auto operator()(T t) const { return t % int_<2>; }
    };

and use it in the three examples. So there is no code duplication and
purely compile-time functions can now also be used as runtime or constexpr
functions for free. This is a large gain IMO.

As far as I can see, everything that can be done with the MPL may also be
done with a variation of this technique. For an example, see [2].

> If you add values to MPL, it would be 1) unnecessarily more complex
> than it needs to be

I don't see why that should be, and my experience suggests something
different. Could you please expand on this point and/or provide evidence
backing this claim?

> and 2) the feature set would be comprised of very
> ugly mongrels.

Again, I don't see why that should be and my experience suggests that
this is not the case.

Regards,
Louis Dionne

[1]: https://github.com/ldionne/hana/blob/master/test/misc/fusion_any.cpp
[2]: https://github.com/ldionne/hana/blob/master/test/type/mpl_equivalent.cpp


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