为 type_traits class 创建一个 "negate" 包装器

Create a "negate" wrapper for a type_traits class

假设我有一个 Filter 元函数来过滤类型列表:

template<template<typename> class TFilter, typename... Ts> 
using Filter = MetaList</* check TFilter<T>{}() for every type in Ts... */>;

元函数可以这样使用:

Filter<std::is_pod, int, char, std::string, int>
// ...returns...
MetaList<int, char, int> 

现在,我想要获取所有不是 POD 的类型。我可以创建一个 FilterNot 元函数,但我实际上也需要其他元函数中的 "negation"。

是否可以为任何 type-trait-like 模板创建否定包装器 class?

所需代码:

Filter<Negate<std::is_pod>, int, char, std::string, int>
// ...returns...
MetaList<std::string> 

一种方法:

#include <iostream>
#include <type_traits>
using namespace std;

template<template <class> class P>
struct invert
{
  template<class... Args>
  struct templ {
    static constexpr bool value = ! P<Args...>::value;
  };
};



int main()
{
  cout << invert<is_pod>::templ<string>::value << endl;
  cout << is_pod<string>::value << endl;

  return 0;
}
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>;

Filter<typename negate<std::is_pod>::result, int, char, std::string, int>;

取决于编译器应该工作。 (IIRC,一些编译器对此很古怪)

我觉得这个语法很别扭,也许可以列出菊花链测试?那么否定只是堆栈上的另一个特征:

template<template<class...>class... Zs>
struct tests {};

然后取 tests 并递归应用 Zs

template<class B>
using negate=std::integral_constant<bool,!B::value>;

filters<tests<negate, std::is_pod>, int, std::string>

另一种方法是进行测试并使它们在 tag<type>{} 上使用 constexpr 函数(很容易做到),这在语法上更容易编写。从 template<class>classconstexpr bool(tag<class>) 并不难。