Subject: Re: [boost] [GSoC][MPL11] Post C++Now update
From: Louis Dionne (ldionne.2_at_[hidden])
Date: 2014-05-20 14:06:56


Eric Niebler <eniebler <at> boost.org> writes:

>
> On 05/19/2014 10:28 AM, Louis Dionne wrote:
> > 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, "");
> >
>
> What does it look like to have a compile-time list containing void? Or
> an array type? Or a function type (i.e., not a pointer to function)? Or
> an abstract type?

    static_assert(
        fmap(trait::add_pointer, list_t<void, int(), char[10]>)
        ==
        list_t<void*, int(*)(), char(*)[10]>
    , "");

    static_assert(
        head(fmap(trait::add_pointer, list_t<void, int, char>))
        ==
        type<void*>
    , "");

    static_assert(std::is_same<
        decltype(
            head(fmap(trait::add_pointer, list_t<void, int, char>))
        )::type,
        void*
>::value, "");

Here's how it works. We provide the following helper for convenience:

    template <typename ...Xs>
    constexpr auto list_t = list(type<Xs>...);

where type<T> is a constexpr variable template of type Type<T>. Type<T>
provides a nested ::type alias to T and also provides adapted versions of
the type_traits as constexpr functions. For example, it is possible to write

    static_assert(trait::add_pointer(type<T>) == type<T*>, "");
    static_assert(std::is_same<decltype(type<T*>)::type, T*>::value, "");

Note that type<T> == type<U> is (roughly) equivalent to std::is_same<T, U>.

The way I see it is that we're trying to represent types as constexpr objects.
When trying to do that, a natural question is: what are the "methods" of these
objects? What are the operations that we can do on those objects? The answer
to that is "whatever operation we can do on a type", which correspond exactly
to the type_traits. So type_traits end up being the API of objects of type
Type<...>, which are nothing but a special case of compile-time-manipulable
objects. When we see things this way, it seems natural to think of the MPL as
a special case of heterogeneous constexpr computation.

There is still one problem that has to do with ADL (it is not limited
to type<>):

    template <bool b = false>
    struct invalid { static_assert(b, "can't instantiate invalid<>"); };

    static_assert(type<invalid<>> != type<void>, "");

This is going to assert in invalid<> because the ADL required by != will
trigger the instantiation of invalid<> . One obvious workaround is to
provide named operators like not_equal, but real operators provide a
large plus for legibility. If someone has an idea, please let me know.

Regards,
Louis Dionne