#include <iostream>
#include <utility>
#include <type_traits>

enum class values {
	zero = 7,
	one = 3,
	two = 1,
	three = -7,
	four = 2,
	five = 4,
};

template<class T, T... ts> struct list {typedef list type;};
template<unsigned max, unsigned... ts> struct make_indexes:make_indexes<max-1, max-1, ts...>{};
template<unsigned... ts> struct make_indexes<0, ts...>:list<unsigned, ts...> {};
template<unsigned max> using make_indexes_t=typename make_indexes<max>::type;

template<class list> struct length_of;
template<class T, T... ts> struct length_of<list<T, ts...>>:std::integral_constant<unsigned, sizeof...(ts)> {};

template<class T, T t, class list> struct index_of;
template<class T, T t, T t0, T...ts> struct index_of<T, t, list<T, t0, ts...>>:
	std::integral_constant< unsigned, index_of<T, t, list<T, ts...>>::value+1 >
{};
template<class T, T t, T...ts> struct index_of<T, t, list<T, t, ts...>>:
	std::integral_constant< unsigned, 1 >
{};
template<class T, unsigned N, class list> struct value_at;
template<class T, unsigned N, T t0, T... ts> struct value_at<T, N, list<T, t0, ts...>>:value_at<T, N-1, list<T, ts...>> {};
template<class T, T t0, T... ts> struct value_at<T, 0, list<T, t0, ts...>>:std::integral_constant<T, t0> {};

template<class T> struct summable {};
template<> struct summable<values> {
  typedef values T;
  typedef list<T, T::zero, T::one, T::two, T::three, T::four, T::five> list_type;
  template<T t>
  using index = index_of< T, t, list_type >;
  template<unsigned N>
  using value = value_at< T, N, list_type >;
};

template<class T, template<T>class indexer>
unsigned index( T t, list<T> ) {
	return -1;
}

template<class T, template<T>class indexer, T t0, T... ts>
unsigned index( T t, list<T, t0, ts...> ) {
	if (t==t0)
		return indexer<t0>::value;
	else
		return index<T, indexer>( t, list<T, ts...>{} );
}

template<class T, template<unsigned>class valuer>
T value( unsigned N, list<unsigned> ) {
	return static_cast<T>(-1);
}
template<class T, template<unsigned>class valuer, unsigned M0, unsigned... Ms>
T value( unsigned N, list<unsigned, M0, Ms...> ) {
	if (N-1==M0)
		return valuer<M0>::value;
	else
		return value<T, valuer>( N, list<unsigned, Ms...>{} );
}


template<typename T>
T sum( T lhs, T rhs ) {
	typedef typename summable<T>::list_type list_type;
	return value<T, summable<T>::template value>( index<T, summable<T>::template index>(lhs, list_type{})+index<values, summable<T>::template index>(rhs, list_type{}), make_indexes_t<length_of<list_type>::value>{} );
}

template<typename T, typename=typename summable<T>::list_type >
T operator+( T lhs, T rhs ) {
	return sum( lhs, rhs );
}

int main() {
	auto two = values::two;
	auto five = values::five;
	std::cout << (two+two==five) << "\n";
	return 0;
}