Skip to content

Instantly share code, notes, and snippets.

@B1Z0N
Last active July 19, 2019 11:41
Show Gist options
  • Save B1Z0N/e122def9e42e2ee198519bb70642feda to your computer and use it in GitHub Desktop.
Save B1Z0N/e122def9e42e2ee198519bb70642feda to your computer and use it in GitHub Desktop.
customizable recursive container print
// code that looks common enough for me to write and post it here
// printing iterable of iterable/values of ... to ostream object
// works on any std conatiner and on any class that meets
// the requirements of Container(named requirement)
// ======================================================================
// compile with g++ container_printer.cpp -o container_printer -std=c++17
// other compilers not guaranteed to compile this
// ======================================================================
#include <iostream>
#include <iterator>
#include <vector>
namespace cmns {
// commons
template <typename T>
std::ostream& __print_container(std::ostream& os, const T& val,
const char* separator = ", ",
const char *inscope = "[",
const char* outscope = "]",
bool end = false)
// prints single value
// end - tells if this the last element in the sequence
{
os << val;
if (!end)
{
// if this is not the end
// print separator too
os << separator;
}
return os;
}
template <
typename T,
template <typename> typename C
>
std::ostream& __print_container(
std::ostream& os, const C<T>& con, const char* separator = ", ",
const char *inscope = "[", const char* outscope = "]", bool end = false
)
// prints iterable of iterbles/values of ...
// end - tells if this the last element in the sequence
{
if (con.empty())
{
// if empty, just print empty parentheses
return os << inscope << " " << outscope;
}
auto prev_end {std::rbegin(con)}; // reverse iterator to (end - 1) element
os << inscope;
for (auto it {std::begin(con)};
it != std::prev(prev_end.base()); // convert reverse iterator to normal
it++) // iterate till the last element
{
__print_container(os, *it, separator, inscope, outscope);
// recursive/polymorphic call to function
}
__print_container(os, *prev_end, separator, inscope, outscope, true);
// but for the last element call it with (end = true)
os << outscope;
if (!end)
{
// if this is not the end
// print separator too
os << separator << std::endl;
}
return os;
}
template <
typename T,
template <typename> typename C
>
std::ostream& print_container(std::ostream& os, const C<T>& con,
const char* separator = ", ", const char *inscope = "[", const char* outscope = "]")
// wrapper for prettyness
{
return __print_container(os, con, separator, inscope, outscope, false);
}
}; // namespace cmns
int main()
{
// some usecases
std::vector<int> _1 { 1, 2, 3 };
std::vector<int> _2 { 5, 4, 0 };
std::vector<int> _3 { 9, 1, 3 };
std::vector<std::vector<int>> vec_of_vecs {_1, _2, _3};
print_container(std::cout, _1);
std::cout << std::endl;
print_container(std::cout, _2);
std::cout << std::endl;
print_container(std::cout, _3);
std::cout << std::endl;
print_container(std::cout, vec_of_vecs);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment