Boost logo

Boost :

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


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