
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