#include <array>
#include <iostream>
#include <cstddef>
#include <cstdint>

//	This template will be instantiated repeatedly with VItems list
//	populated with new items.
template<typename TItem,  TItem... VItems> class
t_PackImpl
{
	//	This template will be selected for second and all other blocks.
	public: template<TItem... VInnerItems> using
	t_Pack = t_PackImpl
	<
		TItem
	//	add all previous items
	,	VItems...
	//	add item holding amount of items in new block
	,	TItem{static_cast<TItem>(sizeof...(VInnerItems))}
	//	add new block items
	,	VInnerItems...
	>;

	//	This method will be called on the last instantiated
	//	template with VItems containing all the items.
	//	Returns array containing all the items with extra 0 item at the end.
	public: static constexpr auto
	to_array(void) -> ::std::array<TItem, sizeof...(VItems) + ::std::size_t{1}>
	{
		return {VItems..., TItem{}};
	}
};

//	This template will be instantiated just once.
//	Starts t_PackImpl instantiation chain.
template<typename TItem> class
t_BeginPack
{
	//	This template will be selected for first block.
	public: template<TItem... VInnerItems> using
	t_Pack = t_PackImpl
	<
		TItem
	//	add item holding amount of items in new block
	,	TItem{static_cast<TItem>(sizeof...(VInnerItems))}
	//	add new block items
	,	VInnerItems...
	>;
};

int main()
{
	{
		constexpr auto items
		{
			t_BeginPack<::std::uint8_t>::t_Pack<42>::to_array()
		};
		for(auto const & item: items)
		{
			::std::cout << static_cast<::std::uint32_t>(item) << ::std::endl;
		}
	}
	::std::cout << "----------------" << ::std::endl;
	{
		constexpr auto items
		{
			t_BeginPack<::std::uint8_t>::t_Pack<0, 1, 2>::to_array()
		};
		for(auto const & item: items)
		{
			::std::cout << static_cast<::std::uint32_t>(item) << ::std::endl;
		}
	}
	::std::cout << "----------------" << ::std::endl;
	{
		constexpr auto items
		{
			t_BeginPack<::std::uint8_t>::
				t_Pack<0, 1, 2>::
				t_Pack<0, 1>::
				t_Pack<0, 1, 2, 3, 4, 5>::to_array()
		};
		for(auto const & item: items)
		{
			::std::cout << static_cast<::std::uint32_t>(item) << ::std::endl;
		}
	}
	return(0);
}
