Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a "negate" wrapper for a type_traits class

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> 
like image 546
Vittorio Romeo Avatar asked May 07 '26 02:05

Vittorio Romeo


1 Answers

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.

like image 60
Yakk - Adam Nevraumont Avatar answered May 08 '26 15:05

Yakk - Adam Nevraumont



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!