#include <iostream>
#include <vector>
#include <valarray>
#include <set>
#include <map>

template <typename F, typename S>
std::ostream &operator <<(std::ostream &o, const std::pair<F, S> &pair)
{
	return o << pair.first << ':' << pair.second;
}

template <template <typename ...> class CONTAINER, typename ... ARGS>
std::ostream &operator <<(std::ostream &o, const CONTAINER<ARGS ...> &container)
{
	o << '[';
	for (const auto &item : container)
	{
		o << item << ' ';
	}
	o << ']';

	return o;
}

template <typename T>
void printContainer(const T &value)
{
	std::cout << value;
}

template <template <typename ...> class CONTAINER, typename ... ARGS>
void printContainer(const CONTAINER<ARGS ...> &container)
{
	std::cout << '[';
	for (const auto &item : container)
	{
		printContainer(item);
		std::cout << ' ';
	}
	std::cout << ']';
}

std::vector<int>                           vi { 1, 2, 3, 4, 5 };
std::vector<std::vector<int>>              vvi { vi, vi, vi };
std::vector<std::vector<std::vector<int>>> vvvi { vvi, vvi, vvi };

std::valarray<int>                               vai { 1, 2, 3, 4, 5 };
std::valarray<std::valarray<int>>                vavai { vai, vai, vai };
std::valarray<std::valarray<std::valarray<int>>> vavavai { vavai, vavai, vavai };

std::set<int>                     si { 1, 2, 3, 4, 5 };
std::set<std::set<int>>           ssi { si, {6, 7}, {8, 9} };
std::set<std::set<std::set<int>>> sssi { ssi, {{10, 11}}, {{12, 14}} };

std::map<float, std::vector<int>> mfvi {{3.14f, {1, 2, 3}}, {6.28f, {4, 5, 6}}};

int main()
{
	std::cout << vi << '\n'
			  << vvi << '\n'
			  << vvvi  << '\n';

	std::cout << vai << '\n'
			  << vavai << '\n'
			  << vavavai  << '\n';

	std::cout << si << '\n'
			  << ssi << '\n'
			  << sssi  << '\n';

	std::cout << mfvi << '\n';

	printContainer(std::string{"Hello world!"});

	return 0;
}