Let's say I have a Filter metafunction that filters a list of types:
template<template<typename> class TFilter, typename... Ts>
using Filter = MetaList</* check TFilter<T>{}() for every type in Ts... */>;
The metafunction can be used like this:
Filter<std::is_pod, int, char, std::string, int>
// ...returns...
MetaList<int, char, int>
Now, I'd like to get all types that are not POD. I could create a FilterNot metafunction, but I actually need the "negation" in other metafunctions as well.
Is it possible to create a negation wrapper for any type-trait-like template class?
Desired code:
Filter<Negate<std::is_pod>, int, char, std::string, int>
// ...returns...
MetaList<std::string>
template<template<class...>class Z>
struct negate {
template<class...Ts>
using result=std::integral_constant<bool, !Z<Ts...>::value>;
};
Filter<negate<std::is_pod>:: template result, int, char, std::string, int>;
or
Filter<typename negate<std::is_pod>::result, int, char, std::string, int>;
depending on compiler should work. (IIRC, some compilers are quirky about this)
As I find this syntax awkward, maybe take a list of tests to daisy chain? Then negation is just another trait on the stack:
template<template<class...>class... Zs>
struct tests {};
then take a tests and apply the Zs recursively.
template<class B>
using negate=std::integral_constant<bool,!B::value>;
filters<tests<negate, std::is_pod>, int, std::string>
Yet another approach is to take your tests and make them constexpr functions on tag<type>{} (easy to do), which are syntactically easier to compose. Going from template<class>class to constexpr bool(tag<class>) isn't hard.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With