Eric Niebler 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)
==
list_t
, "");
static_assert(
head(fmap(trait::add_pointer, list_t))
==
type
, "");
static_assert(std::is_same<
decltype(
head(fmap(trait::add_pointer, list_t))
)::type,
void*
>::value, "");
Here's how it works. We provide the following helper for convenience:
template
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, "");
static_assert(std::is_same)::type, T*>::value, "");
Note that type<T> == type<U> is (roughly) equivalent to std::is_same.
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> != 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