I understand you want to implement a generic stream output independent of the container type. Doing this -- and particularly doing this in a nice way -- is not that easy and requires to cover several aspects, see for example the thread here on SO: Pretty-print C++ STL containers.
Yet, already with a simple first approach you can acquire at least the basic output ability:
//for std::map
template<typename ... Args>
std::ostream& operator<<(std::ostream& os, std::pair<Args ...> const& t)
{
return os<<t.first<<" "<<t.second;
}
template<template <typename ...> class Container, typename ... Args>
std::ostream& operator<<(std::ostream& os, Container<Args ...> const& t)
{
for(auto const& i : t)
{
os<<i<<" ";
}
os<<"\n";
return os;
}
Here, the stream operator calls itself recursively until it arrives at a type for which an overload exists. (For this you usually have to provide a stream output of your custom classes).
Note that the container needs to be range iterable here (one could abstract that further, but to get the idea I think it's sufficient).
With this, the following at least prints something:
int main()
{
std::set<std::vector<std::list<double> > > a{ {{1.0, 2.0}, {3.0}}, {{4.0}} };
std::cout<<a<<std::endl;
std::map<int, std::vector<int> > b{{1,{2,3}}};
std::cout<<b<<std::endl;
}
DEMO ... or, "hey, I didn't say it's nice".
It's questionable, however, whether the formatting suits your needs ... I'd suggest to at least adjust it accordingly -- or better to use the library mentioned above.