假设我有一个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>
答案 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;
}