【问题标题】:Create a "negate" wrapper for a type_traits class为 type_traits 类创建一个“否定”包装器
【发布时间】:2015-04-07 18:21:16
【问题描述】:

假设我有一个过滤类型列表的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> 

【问题讨论】:

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


    【解决方案1】:
    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&lt;type&gt;{} 上进行测试并使其成为constexpr 函数(很容易做到),这在语法上更容易编写。从template&lt;class&gt;classconstexpr bool(tag&lt;class&gt;) 并不难。

    【讨论】:

    • 你可以写!Z&lt;Ts...&gt;{}而不是!Z&lt;Ts...&gt;::value(见问题中的评论:/* check TFilter&lt;T&gt;{}() for every type in Ts... */)。
    • @constructor 同意,但认为 constexpr 支持要求不值得(第一个版本使用了该确切语法)。
    • 啊,constexpr...它的支持就像你一次又一次绊倒的东西。
    • 适用于 clang 3.5 和 gcc 4.9.2,它们是我的目标编译器。太好了!
    【解决方案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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-17
      • 1970-01-01
      • 1970-01-01
      • 2015-03-28
      • 1970-01-01
      • 2018-03-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多