C++ C++;可变模板型滤波变换
问题。 我是模板元编程新手,不确定如何实现 元组上的一种类型过滤转换,当提供该转换时会生成一个类型 具有过滤描述。我相信下面的代码片段演示了 我想要的行为C++ C++;可变模板型滤波变换,c++,templates,metaprogramming,C++,Templates,Metaprogramming,问题。 我是模板元编程新手,不确定如何实现 元组上的一种类型过滤转换,当提供该转换时会生成一个类型 具有过滤描述。我相信下面的代码片段演示了 我想要的行为 enum : int { INCLUDE, EXCLUDE }; template <int filter_val, class T> struct filter { }; int main() { struct A {}; struct B {}; struct C {}; typedef std
enum : int {
INCLUDE,
EXCLUDE
};
template <int filter_val, class T>
struct filter {
};
int
main() {
struct A {};
struct B {};
struct C {};
typedef std::tuple<filter<INCLUDE, A>,
filter<EXCLUDE, B>,
filter<INCLUDE, C>> filters;
typedef filter_all<filters>::type filtered;
static_assert(std::is_same<filtered,
std::tuple<A, C>
>::value,
":(");
return 0;
}
enum:int{
包括,,
排除
};
模板
结构过滤器{
};
int
main(){
结构A{};
结构B{};
结构C{};
typedef std::元组过滤器;
typedef filter_all::type filtered;
静态断言(std::is_same::value,
":(");
返回0;
}
我尝试过的
据我所知,你不能解包超过1个独立的变量模板,所以我想解决这个问题的方法是在递归模板专门化过程中维护两个元组,其中一个表示我们在递归中的位置,而另一个表示目前包含的T
template <template <class ...> class, class ...Unfiltered_Ts>
struct filter_all {
private:
template <class Unfiltered_Ts_Tuple, class Included_Ts_Tuple>
struct filter_all_impl;
// CASE 1: Include T in the result
template <
template <int, class> class, int filter_val, class T, class ...Unfiltered_Ts_impl, // Unfiltered input
template <class ...> class, class ...Included_Ts // Result so far
>
struct filter_all_impl<std::tuple<filter<INCLUDE, T>,
Unfiltered_Ts_impl...>,
std::tuple<Included_Ts...>> {
typedef typename
filter_all_impl<std::tuple<Unfiltered_Ts_impl...>,
std::tuple<Included_Ts..., T> // Append T to result
>::type type;
};
// CASE 2: Don't include T in the result
template <
template <int, class> class, int filter_val, class T, class ...Unfiltered_Ts_impl, // Unfiltered input
template <class ...> class, class ...Included_Ts // Result so far
>
struct filter_all_impl<std::tuple<filter<EXCLUDE, T>,
Unfiltered_Ts_impl...>,
std::tuple<Included_Ts...>
> {
typedef typename
filter_all_impl<std::tuple<Unfiltered_Ts_impl...>,
std::tuple<Included_Ts...> // Don't append T to result
>::type type;
};
// CASE 3: Filtering finished - set the final type as the included T's
template <
template <int, class> class, int filter_val, class T, class ...Unfiltered_Ts_impl,
template <class ...> class, class ...Included_Ts
>
struct filter_all_impl<<>, // empty
std::tuple<Included_Ts...>
> {
// Final step, set type as a tuple of all included Ts
typedef std::tuple<Included_Ts...> type;
};
public:
typedef typename filter_all_impl<
std::tuple<Unfiltered_Ts...>, // Initially contains all unfiltered Ts
std::tuple<> // Initially empty filtered Ts which eventually becomes the return type
>::type type;
};
模板
结构过滤器{
私人:
模板
结构过滤器\u all\u impl;
//案例1:结果中包含T
模板<
模板类,int filter\u val,类T,类…未筛选的\u Ts\u impl,//未筛选的输入
模板类,类…包含\u Ts//到目前为止的结果
>
结构过滤器\u全部\u执行{
typedef typename
过滤器\u所有\u impl::类型;
};
//案例2:结果中不包含t
模板<
模板类,int filter\u val,类T,类…未筛选的\u Ts\u impl,//未筛选的输入
模板类,类…包含\u Ts//到目前为止的结果
>
结构过滤器\u全部\u执行{
typedef typename
过滤所有内容
结构过滤器\u全部\u执行{
//最后一步,将type设置为包含的所有Ts的元组
typedef std::元组类型;
};
公众:
typedef typename过滤器\u all\u impl<
std::tuple,//最初包含所有未筛选的T
std::tuple//最初为空,最终成为返回类型
>::类型类型;
};
我希望有一种更简单的方法来进行此转换,但这是我到目前为止得出的结论,但它远未编译,并且抱怨模板专门化无效。欢迎提供任何指导。首先,定义一个
pick
帮助器,该帮助器返回排除项的空元组,以及一个包含除此之外:
template <typename>
struct pick;
template <typename T>
struct pick<filter<INCLUDE, T>> { using type = std::tuple<T>; };
template <typename T>
struct pick<filter<EXCLUDE, T>> { using type = std::tuple<>; };
完成了
如果您可以修改
过滤器
的实现以公开constepr bool
,则它可以更简单:
template <int filter_val, class T>
struct filter
{
static constexpr bool pick = filter_val == INCLUDE;
using type = T;
};
template <typename T>
struct filter_all;
template <typename... Ts>
struct filter_all<std::tuple<Ts...>>
{
using type = decltype(std::tuple_cat(
std::conditional_t<Ts::pick,
std::tuple<typename Ts::type>, std::tuple<>>{}...
));
};
模板
结构过滤器
{
静态constexpr bool pick=filter_val==INCLUDE;
使用类型=T;
};
模板
结构过滤器;
模板
结构过滤器
{
使用type=decltype(std::tuple\u cat(
std::条件{}。。。
));
};
希望我能对这个问题投两次赞成票。感谢您的清晰解释、测试驱动程序和展示您的尝试。非常感谢!我很高兴我的混乱没有编译,因为这将更容易管理。尽管我不知道我是否在正确的道路上让它做正确的事情,尽管它很丑陋…
t
might不是默认可构造的(因此tuple
),因此您应该将pick::type{}
替换为std::declval
。
template <int filter_val, class T>
struct filter
{
static constexpr bool pick = filter_val == INCLUDE;
using type = T;
};
template <typename T>
struct filter_all;
template <typename... Ts>
struct filter_all<std::tuple<Ts...>>
{
using type = decltype(std::tuple_cat(
std::conditional_t<Ts::pick,
std::tuple<typename Ts::type>, std::tuple<>>{}...
));
};