#include <iostream>
#include <functional>
#include <tuple>

template <typename Type, typename Comp, Type ... values>
struct Sequence
{};

template <typename Type, typename Comp, Type ... values1, Type ... values2>
constexpr decltype (auto) spliceSequences (const Sequence <Type, Comp, values1 ...>,
										   const Sequence <Type, Comp, values2 ...>)
{
	return Sequence <Type, Comp, values1 ..., values2 ...> {};
};

template <typename Type, typename Comp, Type ... values>
struct Sort;

template <typename Type, typename Comp, Type ... values>
constexpr decltype (auto) makeSort (const Sequence <Type, Comp, values ...>)
{
	return typename Sort <Type, Comp, values ...>::seq {};
}

template <typename Type, typename Comp, Type pivot, Type head, Type ... tail>
struct GetLess
{
private:

	using first = typename std::conditional <
		Comp {} (head, pivot),
		Sequence <Type, Comp, head>,
		Sequence < Type, Comp >
	>::type ;

	using second = typename GetLess <Type, Comp, pivot, tail ...>::seq;

public:

	using seq = decltype (spliceSequences (first {}, second {}));
};

template <typename Type, typename Comp, Type pivot, Type head>
struct GetLess <Type, Comp, pivot, head>
{
	using seq = typename std::conditional <
		Comp {} (head, pivot),
		Sequence <Type, Comp, head>,
		Sequence < Type, Comp >>::type ;
};

template <typename Type, typename Comp, Type pivot, Type head, Type ... tail>
struct GetEqual
{
private:

	using first = typename std::conditional <
		(Comp {} (head, pivot) || Comp {} (pivot, head)),
		Sequence <Type, Comp>,
		Sequence <Type, Comp, head >
	>::type ;

	using second = typename GetEqual <Type, Comp, pivot, tail ...>::seq;

public:

	using seq = decltype (spliceSequences (first {}, second {}));
};

template <typename Type, typename Comp, Type pivot, Type head>
struct GetEqual <Type, Comp, pivot, head>
{
	using seq = typename std::conditional <
		(Comp {} (head, pivot) || Comp {} (pivot, head)),
		Sequence <Type, Comp>,
		Sequence <Type, Comp, head >
	>::type ;
};

template <typename Type, typename Comp, Type pivot, Type head, Type ... tail>
struct GetGreater
{
private:

	using first = typename std::conditional <
		Comp {} (pivot, head),
		Sequence <Type, Comp, head>,
		Sequence < Type, Comp >
	>::type ;

	using second = typename GetGreater <Type, Comp, pivot, tail ...>::seq;

public:

	using seq = decltype (spliceSequences (first {}, second {}));
};

template <typename Type, typename Comp, Type pivot, Type head>
struct GetGreater <Type, Comp, pivot, head>
{
	using seq = typename std::conditional <
		Comp {} (pivot, head),
		Sequence <Type, Comp, head>,
		Sequence < Type, Comp >
	>::type ;
};

template <typename Type, typename Comp, Type ... values>
struct Sort
{
private:

	constexpr static Type pivot =
		std::get <sizeof ... (values) / 2> (std::make_tuple (values ...));

public:

	using seq = decltype (spliceSequences (
		makeSort (typename GetLess <Type, Comp, pivot, values ...>::seq {}),
		spliceSequences (typename GetEqual <Type, Comp, pivot, values ...>::seq {},
						 makeSort (typename GetGreater <Type, Comp, pivot, values ...>::seq {}))
		));
};

template <typename Type, typename Comp, Type head>
struct Sort <Type, Comp, head>
{
	using seq = Sequence <Type, Comp, head>;
};

template <typename Type, typename Comp>
struct Sort <Type, Comp>
{
	using seq = Sequence <Type, Comp>;
};

template <typename Type, typename Comp, Type head, Type ... tail>
void printSequence (Sequence <Type, Comp, head, tail ...>)
{
	std::cout << head << ' ';
	printSequence (Sequence <Type, Comp, tail ...> {});
}

template <typename Type, typename Comp, Type head>
void printSequence (Sequence <Type, Comp, head>)
{
	std::cout << head << std::endl;
}

int main ()
{
	printSequence (Sort <int, std::greater <int>, 3, 2, 7, 1, -1, 1, 1488, 1, 1, 1, 2, -1, 25, 14, 7, 8, 7, 25>::seq {});

	return 0;
}