这是我的代码:
template<
template <typename TSEvent,
typename ...TSEvents> typename V,
typename... Filtered>
constexpr auto filter() {
if constexpr(sizeof...(TSEvents) == 0) {
return type_list<Filtered...>{};
}
if constexpr(is_default_constructible<TSEvent>::value) {
return filter<<TSEvents...>, Filtered...>();
}
return filter<<TSEvents...>, Filtered...>();
}
但是我得到此错误,size...(TSEvents)
,TSEvents
未声明。无论如何,我是否可以访问嵌套模板中的TSEvents
?
答案 0 :(得分:2)
通常通过另一个间接级别,通常是我们可以专门研究的struct
。
例如:
namespace detail
{
template<class...>
struct filter_t;
template<template<class, class...> class V, class TSEvent, class... TSEvents, class... Filtered>
struct filter_t<V<TSEvent,TSEvents...>, Filtered...>
{
static constexpr auto filter() {
return sizeof...(TSEvents);
}
};
} // detail
template<class... T>
constexpr auto filter()
{
return detail::filter_t<T...>::filter();
}
template<class T, class...U>
struct type_list{};
int main()
{
std::cout << filter<type_list<int, int, int>, int>();
}
答案 1 :(得分:2)
只需提供另一个选项,您就可以仅使用函数来完成此操作。
#include <iostream>
using namespace std;
template<typename...>
struct type_list{};
template < template <typename...> typename T,typename A,typename... B, typename... Filtered>
constexpr auto filter_impl(T<A,B...>*,type_list<Filtered...>)
{
using filtered_list = std::conditional_t<is_arithmetic<A>::value,
type_list<Filtered...,A>,
type_list<Filtered...>>;
if constexpr (sizeof...(B) == 0)
return filtered_list();
else
return filter_impl( (T<B...>*)0, filtered_list());
}
template <typename T>
constexpr auto filter()
{
return filter_impl( (T*)0,type_list<>());
}
struct not_arethmetic{};
int main() {
auto b = filter< type_list<not_arethmetic,int,bool,not_arethmetic,double> >();
static_assert(std::is_same< decltype(b) , type_list<int,bool,double>>::value);
return 0;
}
一件事,在您的原始示例中,您的第一个if表达式将意味着不检查最终的TSEvent,因为如果可变的TSEvents ...的大小为零,它将返回最终的TSEvent,但是将有一个最后的元素检查is_default_constructible。
此外,您可能会发现this帖子对模板模板参数名称很有用。
答案 2 :(得分:1)
但是我得到这个错误,大小...(TSEvents),未声明TSEvents。无论如何,我是否可以在嵌套模板中访问TSEvents?
简短回答:否。
长答案:
template<
template <typename TSEvent,
typename ...TSEvents> typename V,
typename... Filtered>
constexpr auto filter()
您为filter()
函数设置了两个模板参数。
第一个与TSEvents
可变参数列表相关的是一个模板模板参数,该参数接收一个或多个类型参数。
但是您的函数没有收到基于该模板模板的类型(具有固定的TSEvent
类型和固定的TSEvents
);接收模板模板。
因此测试size...(TSEvents)
没有意义,因为对于filter()
而言,
修复了TSEvents
列表。
以另一种方式解释这一点...您可以通过这种方式调用过滤器
filter<std::tuple, short, int, long>();
询问sizeof...(TSEvents)
询问多少个类型包含std::tuple
,其中std::tuple
仅是类型的容器,而没有包含的类型。
如果您想在filter()
函数中执行某种操作,则需要一个 type 模板参数,而不是template-template参数。
使用类(请参阅AndyG的答案)更为简单,您可以在其中使用部分专业化(对于不能使用的函数),也可以在函数接收到可以推论出类型的参数时使用函数。
假设您的filter()
收到了V<SomeTypes...>
类型的对象和std::tuple<Filtered...>
类型的对象,则可以编写以下内容(警告:未经测试的代码)
template<
template <typename ...> typename V,
typename TSEvent, typename ... TSEvents, typename... Filtered>
constexpr auto filter (V<TSEvent, TSEvents...> const & v,
std::tuple<Filtered...> const & t) {
/* some code where you can use also TSEvent and TSEvents... */
}
通过这种方式从TSEvent
推论得出TSEvents...
和v
。