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;