C++ 过滤给定模板谓词的类型的元组列表

C++ 过滤给定模板谓词的类型的元组列表,c++,c++11,templates,c++14,template-meta-programming,C++,C++11,Templates,C++14,Template Meta Programming,我本来想问一个问题,但在写的时候自己找到了答案。 问题是如何过滤给定模板谓词的元组而不专门化它 用法示例: using tuple_list_t = std::tuple<std::string, int, none, double, char, abc, bool>; using tuple_found_expected_t = std::tuple<int, double, char, bool>; // filtering a tuple

我本来想问一个问题,但在写的时候自己找到了答案。 问题是如何过滤给定模板谓词的元组而不专门化它

用法示例:

    using tuple_list_t = std::tuple<std::string, int, none, double, char, abc, bool>;
    using tuple_found_expected_t = std::tuple<int, double, char, bool>;

    // filtering a tuple 
    using tuple_filtered_t = filter_t<tuple_list_t, std::is_fundamental>;

    static_assert(std::is_same<tuple_filtered_t, tuple_found_expected_t>(), "");
使用tuple\u list\u t=std::tuple;
使用tuple\u found\u expected\u t=std::tuple;
//过滤元组
使用tuple_filtered_t=filter_t;
静态断言(std::is_same(),“”);

如果有人对这个问题有任何建议或意见,请写一个答案或评论。

这里是一个模板SFINAE结构的版本,用于过滤给定SFINAE谓词类型的
std::tuple
。因此,调用看起来就像使用带有一元谓词的STL算法

例如:

    using tuple_list_t = std::tuple<std::string, int, none, double, char, abc, bool>;
    using tuple_found_expected_t = std::tuple<int, double, char, bool>;

    // filtering a tuple 
    using tuple_filtered_t = filter_t<tuple_list_t, std::is_fundamental>;

    static_assert(std::is_same<tuple_filtered_t, tuple_found_expected_t>(), "");
  • 使用
    sfinaeprodicate::value
    删除产生false的类型
    现在有了一种使用递归SFINAE模板专门化的方法,但它需要大量的键入,可能还需要大量的冗余代码生成。在调试中编译时,后者是一个很大的问题,因为MinGW将因汇编程序错误
    文件太大而失败,到目前为止,我还没有找到有效的方法来避免这个问题(优化pragmas什么也不做)。但这超出了本问题/答案的范围。
    我的方法是使用type=decltype(std::tuple_cat(append_if_t())
    append\u如果\u t
    返回一个元组,在某些情况下该元组将为空,然后所有元组都会连接到一个带有
    std::tuple\u cat的最终元组中

    因此,
    append\if\t
    有N个专门化,可以被编译器重用,没有递归中间专门化
  • 代码如下:

            template<typename Tuple, typename T, template<typename> class /*SFINAEPredicate*/, typename = T>
            struct append_if;
    
            template<typename T, template<typename> class SFINAEPredicate, typename ... Types>
            struct append_if<std::tuple<Types...>, T, SFINAEPredicate, T>
            {
                using type = typename std::conditional<SFINAEPredicate<T>::value,
                        std::tuple<Types..., T>, std::tuple<Types...>>::type;
            };
    
            template<typename Tuple, typename T, template<typename> class SFINAEPredicate, typename = T>
            using append_if_t = typename append_if<Tuple, T, SFINAEPredicate>::type;
    
            // TODO: function to traverse a tuple and find a type (index) that can be used to initialize a POD element
            // pass a template parameter (trait validator) that accepts a type
    
            // template for find_if in tuple
            template<typename Tuple, template<typename> class /*SFINAEPredicate*/, typename = void>
            struct filter;
    
            template<template<typename> class SFINAEPredicate, typename ... Types>
            struct filter<std::tuple<Types...>, SFINAEPredicate, void>
            {
                using type = decltype(std::tuple_cat(append_if_t<std::tuple<>, Types, SFINAEPredicate>()...));
            };
    
            template<typename Tuple, template<typename> class SFINAEPredicate, typename = void>
            using filter_t = typename filter<Tuple, SFINAEPredicate>::type;
    
    
    模板
    结构append_if;
    模板
    结构附加\u如果
    {
    使用type=typename std::conditional::type;
    };
    模板
    使用append\u if\u t=typename append\u if::type;
    //TODO:遍历元组并查找可用于初始化POD元素的类型(索引)的函数
    //传递接受类型的模板参数(特征验证器)
    //在元组中查找\u if的模板
    模板
    结构过滤器;
    模板
    结构过滤器
    {
    使用type=decltype(std::tuple_cat(append_if_t()…);
    };
    模板
    使用filter\u t=typename filter::type;
    
    对不起,我觉得你的解决方案太复杂了。特别是关于SFINAE部分(为什么
    无效
    ?)

    那么简单地说如下呢

    template <typename, template <typename...> class>
    struct filter;
    
    template <typename ... Ts, 
              template <typename...> class Pred>
    struct filter<std::tuple<Ts...>, Pred>
     { 
       using type = decltype(std::tuple_cat(std::declval<
          std::conditional_t<Pred<Ts>::value,
                             std::tuple<Ts>,
                             std::tuple<>>>()...));
     };
    
    template <typename Tpl, 
              template <typename...> class Pred>
    using filter_t = typename filter<Tpl, Pred>::type;
    
    模板
    结构过滤器;
    模板
    结构过滤器
    { 
    使用type=decltype(std::tuple_cat(std::declval<
    std::条件的(t>()…);
    };
    模板
    使用filter\u t=typename filter::type;
    
    由于某种原因,我的代码在没有模板typename专门化的情况下无法编译。现在是了。你的版本确实更短更简单。
    template <typename, template <typename...> class>
    struct filter;
    
    template <typename ... Ts, 
              template <typename...> class Pred>
    struct filter<std::tuple<Ts...>, Pred>
     { 
       using type = decltype(std::tuple_cat(std::declval<
          std::conditional_t<Pred<Ts>::value,
                             std::tuple<Ts>,
                             std::tuple<>>>()...));
     };
    
    template <typename Tpl, 
              template <typename...> class Pred>
    using filter_t = typename filter<Tpl, Pred>::type;