I think the emphasis is a little too focused on compilation times and not
enough on the interface. That being said, a comment about the type-only
predicate: Thanks to constexpr, function overloading, user-defined
literals, explicit operator bool, and variable templates, that example
could actually look like this:
static_assert(any(odd{}, list(1_udl, 2_udl)), "1 or 2 should be odd.");
And also allow the following natural looking expressions:
static_assert(count(odd{}, list(1_udl, 2_udl, 3_udl)) == 2_udl, "Incorrect
count of odd numbers.");
static_assert(type<int> == type, "Integer literal not an
int.");
static_assert(common_type(type<int>, type<unsigned>, type<char>,
type<signed char>) == type<unsigned>, "Incorrect common_type.");
User-defined literal name of udl (user defined literal) chosen as a
placeholder to avoid that being the focus. It could be anything from _mpl
to _type to _t.
Long compile times in a C++11 metaprogramming world are primarily defined
by the number of arguments passed to constexpr functions (calling two
constexpr functions with 3000 arguments instead of one constexpr function
with 3000 arguments is a huge time and memory sink) and template
instantiation / constexpr recursion depth. Neither of those are especially
dictated by choice in interface, and I would hate to see a better interface
abandoned due to premature optimization.