#include <iostream>
#include <tuple>
#include <type_traits>
using namespace std;

template<int Ins, int Outs>
class Filter
{
    // implementation
};

template <int... Args>
struct FiltersFor;

template <typename Tuple1, typename Tuple2>
using tuple_cat_t = decltype(std::tuple_cat(std::declval<Tuple1>(),
											std::declval<Tuple2>())); 

template <int Ins, int Outs, int... Others>
struct FiltersFor<Ins,Outs,Others...>
{
	using type = tuple_cat_t<std::tuple<Filter<Ins,Outs>>, typename FiltersFor<Outs,Others...>::type>;	
};

template <int Dummy>
struct FiltersFor<Dummy>
{
	using type = std::tuple<>;
};

template <>
struct FiltersFor<>
{
	using type = std::tuple<>;
};

template<int... args>
using Chain = typename FiltersFor<args...>::type;


static_assert(std::is_same<Chain<1,2,3,4>, std::tuple<Filter<1,2>,Filter<2,3>,Filter<3,4>>>::value, "wat");
static_assert(std::is_same<Chain<1,2>, std::tuple<Filter<1,2>>>::value, "wat");
static_assert(std::is_same<Chain<>, std::tuple<>>::value, "wat");

int main() {
	return 0;
}