Is there any reason why the standard specifies them as template structs instead of simple boolean constexpr?
In an additional question that will probably be answered in a good answer to the main question, how would one do enable_if stuff with the non-struct versions?
One reason is that
constexprfunctions can’t provide a nestedtypemember, which is useful in some meta-programming situations.To make it clear, I’m not talking only of transformation traits (like
make_unsigned) that produce types and obviously can’t be madeconstexprfunctions. All type traits provide such a nestedtypemember, even unary type traits and binary type traits. For exampleis_void<int>::typeisfalse_type.Of course, this could be worked around with
std::integral_constant<bool, the_constexpr_function_version_of_some_trait<T>()>, but it wouldn’t be as practical.In any case, if you really want function-like syntax, that is already possible. You can just use the traits constructor and take advantage of the constexpr implicit conversion in
integral_constant:For transformation traits you can use a template alias to obtain something close to that syntax: