为type_traits类创建一个“否定”包装器

时间:2015-02-07 18:07:07

标签: c++ templates metaprogramming template-meta-programming typetraits

假设我有一个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元函数,但我实际上也需要其他元函数中的“否定”。

是否可以为任何 type-trait 类似的模板类创建一个否定包装器?

所需代码:

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

2 个答案:

答案 0 :(得分:3)

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>class转到constexpr bool(tag<class>)并不难。

答案 1 :(得分:2)

一种方法:

#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;
}