#include <array>
#include <iostream>
#include <utility>

template<int VRange, int VRepCount, int VValueRIndex = VRepCount> class
t_Looper
{
	public: template<typename TAction> static void
	process(::std::array<int, VRepCount> & values, TAction && action)
	{
		for(;;)
		{
			t_Looper<VRange, VRepCount, VValueRIndex - 1>::process(values, ::std::forward<TAction>(action));
			auto & value{values[VRepCount - VValueRIndex]};
			if((VRange - 1) != value)
			{
				++value;
			}
			else
			{
				value = 0;
				break;
			}
		}
	}
};

template<int VRange, int VRepCount> class
t_Looper<VRange, VRepCount, 0>
{
	private: template<int... VIndexes, typename TAction> static void
	invoke(::std::integer_sequence<int, VIndexes...>, ::std::array<int, VRepCount> const & values, TAction && action)
	{
		action(values[VIndexes]...);
	}

	public: template<typename TAction> static void
	process(::std::array<int, VRepCount> & values, TAction && action)
	{
		invoke(::std::make_integer_sequence<int, VRepCount>(), values, ::std::forward<TAction>(action));
	}
};

template<int VRange, int VRepCount, typename TAction> void
multiloop(TAction && action)
{
	::std::array<int, VRepCount> values{};
	t_Looper<VRange, VRepCount>::process(values, ::std::forward<TAction>(action));
}

int main()
{
	multiloop<3, 2>([](int i, int j){::std::cout << i << " " << j << ::std::endl;});
	multiloop<3, 4>([](int i, int j, int k, int l){::std::cout << i << " " << j << " " << k << " " << l << ::std::endl;});
	return(0);
}
