Reputation: 342
I'm trying to create a macro that works like the "where" constraint in higher-level languages:
#define where(T, ...) typename std::enable_if< /* tricky part */ >::type
// should expand like so: trait1<T>::value && trait2<T>::value ... traitN<T>::value
So that VA_ARGS is list of traits and is used like so:
template<class T,
where(T, std::is_default_constructible, std::is_class)>
class A { };
Is that possible?
Upvotes: 0
Views: 122
Reputation: 342
I am sorry to bring this question back from the dead after four years, but I think I have a better answer that does exactly what I was aiming for at the time. (Not needing to specify the argument for the predicates multiple times.)
template <typename T, template <typename> class... Predicates>
using where_t = std::enable_if_t<std::conjunction_v<Predicates<T>...>>;
template <typename T, typename = where_t<T, std::is_default_constructible, std::is_class>>
struct my_struct
{
};
Upvotes: 0
Reputation: 477580
Maybe something like this:
#define WHERE(P, ...) join_predicate<P, __VA_ARGS__>::value
template <template <typename> typename Pred, typename ...Args>
struct join_predicate : std::conjunction<Pred<Args>...> {};
Usage:
std::enable_if_t<WHERE(std::is_default_constructible, Foo, Bar, Quz), int>
I would probably not even bother with the macro and just use a real C++ construct, maybe:
template <template <typename> typename P, typename ...Args>
constexpr bool where_v = join_predicate<P, Args...>::value;
Upvotes: 1