#include <iostream>

template<unsigned> struct size {};

    template<unsigned...Is> struct indexes {typedef indexes<Is...> type;};
    template<class lhs, class rhs> struct concat_indexes;
    template<unsigned...Is, unsigned...Ys> struct concat_indexes<indexes<Is...>, indexes<Ys...>>{
    	typedef indexes<Is...,Ys...> type;
    };
    template<class lhs, class rhs>
    using ConcatIndexes = typename concat_indexes<lhs, rhs>::type;
    
    template<unsigned min, unsigned count> struct make_indexes:
    	ConcatIndexes<
    		typename make_indexes<min, count/2>::type,
    		typename make_indexes<min+count/2, (count+1)/2>::type
    	>
    {};
    template<unsigned min> struct make_indexes<min, 0>:
    	indexes<>
    {};
    template<unsigned min> struct make_indexes<min, 1>:
    	indexes<min>
    {};
	template<unsigned max, unsigned min=0>
	using MakeIndexes = typename make_indexes<min, max-min>::type;

    template< typename L, typename R, unsigned I >
    struct helper_helper {
    	static R func( L&& l ) { return std::forward<L>(l)(size<I>()); }
    };
    template<typename L, unsigned... Is>
    auto
    dispatch_helper(indexes<Is...>, L&& l, unsigned i)
    -> decltype( std::declval<L>()(size<0>()) )
    {
      typedef decltype( std::declval<L>()(size<0>()) ) R;
      // some compilers have problems with this line.
      // you can write a helper class replace the lambda below if so:
      typedef R(*F)(L&&);
      static const F table[] = {
        helper_helper<L, R, Is>::func...
      };
      return table[i]( std::forward<L>(l) );
    };
    template<unsigned Max, typename L>
    auto
    dispatch(L&& l, unsigned i)
    -> decltype( std::declval<L>()(size<0>()) )
    {
      return dispatch_helper( MakeIndexes<Max>(), std::forward<L>(l), i );
    };


struct test {
	template<unsigned I>
	int operator()( size<I> ) { std::cout << I << "\n"; return I; }
};

int main() {
	int x = dispatch<1<<14>( test{}, 3 );
	std::cout << x << "\n";
	// your code goes here
	return 0;
}