#include <iostream>
using namespace std;

template <bool b, typename T, typename U>
class Select;

template <typename T, typename U>
class Select<true, T, U>
{
public:
    using type = T;
};

template <typename T, typename U>
class Select<false, T, U>
{
public:
    using type = U;
};


template <typename Type>
class EmptyList
{
public:
    using type = Type;
};

template <typename Type, Type Value>
class ValueWrapper
{
public:
    using type = Type;
    static constexpr Type value = Value;
};

template <typename Left, typename Right>
class Pair
{
public:
    using first = Left;
    using rest = Right;
};

template <typename Type, Type First, Type ... Rest>
class Make_List
{
public:
    using result = Pair<ValueWrapper<Type, First>,
          typename Make_List<Type, Rest...>::result>;
};

template <typename Type, Type Last>
class Make_List<Type, Last>
{
public:
    using result = Pair<ValueWrapper<Type, Last>, EmptyList<Type>>;
};

template <typename T, T val>
class DivBy5
{
public:
    static constexpr bool value = val % 5 == 0;
};

template <typename List, template <typename T, T v> class Pred>
class Filter;

template <typename Type, template <typename T, T v> class Pred>
class Filter<EmptyList<Type>, Pred>
{
public:
    using result = EmptyList<Type>;
};

template <typename First, typename Rest, template <typename T, T v> class Pred>
class Filter<Pair<First, Rest>, Pred>
{
public:
    using result = typename Select<Pred<typename First::type, First::value>::value,
          Pair<First, typename Filter<Rest, Pred>::result>,
          typename Filter<Rest, Pred>::result>::type;
};

template <typename Type>
void PrintList(EmptyList<Type>)
{
}

template <typename First, typename Rest>
void PrintList(Pair<First, Rest>)
{
    cout << First::value << endl;
    PrintList(Rest());
}

int main()
{
    using original = Make_List<int, 1, 2, 3, 10, 15, 20, 25, 123, 15>::result;
    using filtered = Filter<original, DivBy5>::result;
    PrintList(original());
    cout << endl;
    PrintList(filtered());
}
