Generic printing of 2D containers - c++

this template prints the content of an 2D vector
how would you generalize this template so it works for every STL container ?
template<class T>
void printVector(std::vector<std::vector<T>> const &matrix) {
for (std::vector<T> row : matrix) {
for (T val : row) {
std::cout << val << " ";
}
std::cout << '\n';
}
}
Is there maybe "print" that allows me to print anything, no matter what I put into it ? (n-dimensional containers, strings, etc ?)

Just take any type and use range based loops. Your only problem is that you specified that is was a std::vector.
template<class T>
void print2Dcontainer(const T &matrix)
{
for (const auto &row : matrix)
{
for (const auto &val : row) std::cout << val << ' ';
std::cout << '\n';
}
}
My version above has no safety for passing something that will cause a compile error (e.g. passing 7). Fancy SFINAE could be added to remove this potential issue, but I'd only do so for library code.

Related

Iterate throught n-dimensional vector c++

I wanted to write my own code to iterate over an n dimensional vector (where the dimension is known). Here is the code:
void printing(const auto& i, const int dimension){
int k= dimension;
for(const auto& j: i){
if(k>1){
cout<<"k: "<<k<<endl;
printing(j, --k);
}
else{
//start printing
cout<<setw(3);
cout<<j; //not quite sure about this line
}
cout<<'\n';
}
}
I get an error:
main.cpp:21:5: error: ‘begin’ was not declared in this scope
for(const auto& j: i){
^~~
Could someone help me to correct it or give me a better way to print the vector?
Thanks in advance for your time.
If the dimensions are known at compile-time, this can be solved easily with a template that takes dimensions as the non-type argument.
template <std::size_t Dimensions>
void printing(const auto& i){
if constexpr (Dimensions != 0) {
for(const auto& j: i){
// I'm not sure if it is intentional to print 'k' each iteration,
// but this is kept for consistency with the question
cout<<"k: " << Dimensions << endl;
printing<Dimensions - 1u>(j);
}
} else {
cout << setw(3);
cout << j;
cout << '\n';
}
}
The use would be, for a 2d vector:
printing<2>(vec);
Live Example
However, if you always know that const auto& i will be a std::vector type, you can potentially solve this even easier by just not using auto arguments at all, and instead use template matching:
// called only for the vector values
template <typename T>
void printing(const std::vector<T>& i){
for(const auto& j: i){
// possibly compute 'k' to print -- see below
printing(j);
}
}
// Only called for non-vector values
template <typename T>
void printing(const T& v) {
cout << setw(3);
cout << v;
cout << '\n';
}
Live Example
To compute the "dimension" of the vector, you can write a recursive type-trait for that:
#include <type_traits> // std::integral_constant
// Base case: return the count
template <std::size_t Count, typename T>
struct vector_dimension_impl
: std::integral_constant<std::size_t, Count> {};
// Recursive case: add 1 to the count, and check inner type
template <std::size_t Count, typename T, typename Allocator>
struct vector_dimension_impl<Count, std::vector<T,Allocator>>
: vector_dimension_impl<Count + 1u, T> {};
// Dispatcher
template <typename T>
struct vector_dimension : vector_dimension_impl<0u, T> {};
// Convenience access
template <typename T>
inline constexpr auto vector_dimension_v = vector_dimension<T>::value;
// Simple tests:
static_assert(vector_dimension_v<std::vector<int>> == 1u);
static_assert(vector_dimension_v<std::vector<std::vector<int>>> == 2u);
static_assert(vector_dimension_v<std::vector<std::vector<std::vector<int>>>> == 3u);
Live Example
With the above recursive trait, you can get the "dimension" of each templated vector type, without requiring the user to pass in the value at all.
If you still wanted to print k: each time, you can use the above simply with:
cout << "k: " << vector_dimension_v<T> << endl;
This only works if the type is known to be a vector -- but it could be written using concepts to work with anything following the abstract definition of something like a vector as well.
If you want this to work with any range-like type, then you could replace the vector-overload with a requires(std::ranges::range<T>) instead, and change the template-specializations for finding the dimension to also use the same. I won't pollute the answer with all this code since it's largely the same as above -- but I'll link to it in action below:
Live Example
I have made a function that can print any n-dimensional iterable container:
template<typename Object, typename Iterable>
void Print(
const Iterable& iterable,
const string& separatorDimensions = "\n",
const function<void(const Object&)>& funcPrintElem = [] (const Object& obj) {
static_assert(
is_arithmetic_v<Object> || is_same_v<remove_const_t<remove_pointer_t<Object>>, char>,
R"(The object from the innermost range is not a built-in/c-string type, please provide a valid print element function.)"
);
cout << obj << ' ';
}
) {
if constexpr (ranges::range<Iterable>) {
ranges::for_each(iterable, [&] (const auto& it) { Print(it, separatorDimensions, funcPrintElem); });
cout << separatorDimensions;
} else {
funcPrintElem(iterable);
}
}
The function has a default std::function that can print any built-in type like int, unsigned char, long long etc... and the c-string like char* or const char*, if you have another object like a pair or tuple or an object of your class you can pass a function that prints your object.
You can use the function like this: (you must explicitly tell the function your inner most object like below)
int main() {
cout << "v: " << endl;
vector<uint16_t> v { 1, 2, 3 };
Print<uint16_t>(v);
cout << endl << "ll: " << endl;
list<list<const char*>> ll { { "a", "b" }, { "c", "d" } };
Print<const char*>(ll);
struct smth {
int a;
char b;
};
cout << endl << "smths: " << endl;
vector<smth> smths { { 14, '0' }, { 18, '1' } };
Print<smth>(smths, "\n", [] (const smth& obj) { cout << "a = " << obj.a << ", b = " << obj.b << endl; });
return 0;
}
The function can be found here, maybe I will update in the future to support more things.
Edit: You need to have at least c++20 for this function to work

Outputting a Returned pair Without a Temporary

Let's say that I have a function: pair<int, int> foo() I want to directly output both elements of this without using a temporary.
Is there a way that I can output this, or maybe convert it into a string to output? Could I perhaps use tie to do this?
Here's what I'm trying to do with the temporary:
const auto temporary = foo();
cout << temporary.first << ' ' << temporary.second << endl;
In c++17 standard, you can use structured binding declaration
std::pair<int, int> get_pair()
{
return {10, 20};
}
int main()
{
auto [x, y] = get_pair();
std::cout << x << " " << y << std::endl;
return 0;
}
No. You can't write that function without using a non-temporary. If you really need to, you should probably change the structure of your code. Technically, you could also use a global variable (although I strongly do not recommend this). I don't think tie would work for what you want it for either.
You can create a small class that wraps the std::pair, and enable output streams to print it via operator<<:
template<typename PairT>
struct printable {
const PairT& p;
printable(const PairT& p)
: p{p}
{}
};
template<typename CharT, typename PairT>
std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& out, const printable<PairT>& pair) {
out << pair.p.first << ' ' << pair.p.second;
return out;
}
Then you can use it like this:
auto foo() {
return std::pair<int, int>(1, 2);
}
int main() {
std::cout << printable(foo());
}
Live example
Of course, you could also just enable the printing directly for an std::pair...
template<typename CharT, typename A, typename B>
std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& out, const std::pair<A, B>& pair) {
out << pair.first << ' ' << pair.second;
return out;
}
// (...)
std::cout << foo(); // And this would work just fine
... but I don't really recommend it, specially on a header, since you would be basically changing behavior of standard types and your colleagues (or yourself, in the future) may be confused by it.

How to implement template function like add(T a, K b) with std::any elegant and without template? [duplicate]

I have a "dictionary" std::map<std::string, boost::any> (or std::any, if you want) that can possibly be nested. Now, I would like to display the map. Since boost::any obviously doesn't play nicely with <<, things are getting a little nasty. So far, I'm checking the type, cast it, and pipe the cast to cout:
for (const auto &p: map) {
std::cout << std::string(indent + 2, ' ') << p.first << ": ";
if (p.second.type() == typeid(int)) {
std::cout << boost::any_cast<int>(p.second);
} else if (p.second.type() == typeid(double)) {
std::cout << boost::any_cast<double>(p.second);
} else if (p.second.type() == typeid(std::string)) {
std::cout << boost::any_cast<std::string>(p.second);
} else if (p.second.type() == typeid(const char*)) {
std::cout << boost::any_cast<const char*>(p.second);
} else if (p.second.type() == typeid(std::map<std::string, boost::any>)) {
show_map(
boost::any_cast<std::map<std::string, boost::any>>(p.second),
indent + 2
);
} else {
std::cout << "[unhandled type]";
}
std::cout << std::endl;
}
std::cout << std::string(indent, ' ') << "}";
This prints, for example
{
fruit: banana
taste: {
sweet: 1.0
bitter: 0.1
}
}
Unfortunately, this is hardly scalable. I'd have to add another else if clause for every type (e.g., float, size_t,...), which is why I'm not particularly happy with the solution.
Is there a way to generalize the above to more types?
One thing you can do to lessen (but not remove) the pain is to factor the type determination logic into one support function, while using static polymorphism (specifically templates) for the action to be applied to the values...
#include <iostream>
#include <boost/any.hpp>
#include <string>
struct Printer
{
std::ostream& os_;
template <typename T>
void operator()(const T& t)
{
os_ << t;
}
};
template <typename F>
void f_any(F& f, const boost::any& a)
{
if (auto p = boost::any_cast<std::string>(&a)) f(*p);
if (auto p = boost::any_cast<double>(&a)) f(*p);
if (auto p = boost::any_cast<int>(&a)) f(*p);
// whatever handling for unknown types...
}
int main()
{
boost::any anys[] = { std::string("hi"), 3.14159, 27 };
Printer printer{std::cout};
for (const auto& a : anys)
{
f_any(printer, a);
std::cout << '\n';
}
}
(With only a smidge more effort, you could have the type-specific test and dispatch done for each type in a variadic template parameter pack, simplifying that code and the hassle of maintaining the list. Or, you could just use a preprocessor macro to churn out the if-cast/dispatch statements....)
Still - if you know the set of types, a boost::variant is more appropriate and already supports similar operations (see here).
Yet another option is to "memorise" how to do specific operations - such as printing - when you create your types:
#include <iostream>
#include <boost/any.hpp>
#include <string>
#include <functional>
struct Super_Any : boost::any
{
template <typename T>
Super_Any(const T& t)
: boost::any(t),
printer_([](std::ostream& os, const boost::any& a) { os << boost::any_cast<const T&>(a); })
{ }
std::function<void(std::ostream&, const boost::any&)> printer_;
};
int main()
{
Super_Any anys[] = { std::string("hi"), 3.14159, 27 };
for (const auto& a : anys)
{
a.printer_(std::cout, a);
std::cout << '\n';
}
}
If you have many operations and want to reduce memory usage, you can have the templated constructor create and store a (abstract-base-class) pointer to a static-type-specific class deriving from an abstract interface with the operations you want to support: that way you're only adding one pointer per Super_Any object.
Since you're already using Boost you could consider boost::spirit::hold_any.
It already has pre-defined streaming operators (both operator<<() and operator>>()).
Just the embedded type must have the corresponding operator defined, but in your use context this seems to be completely safe.
Despite being in the detail namespace, hold_any is quite widespread and almost a ready-to-use boost:any substitute (e.g. Type Erasure - Part IV, Why you shouldn’t use boost::any)
A recent version of Boost is required (old versions had a broken copy assignment operator).

cout map with boost::any

I have a "dictionary" std::map<std::string, boost::any> (or std::any, if you want) that can possibly be nested. Now, I would like to display the map. Since boost::any obviously doesn't play nicely with <<, things are getting a little nasty. So far, I'm checking the type, cast it, and pipe the cast to cout:
for (const auto &p: map) {
std::cout << std::string(indent + 2, ' ') << p.first << ": ";
if (p.second.type() == typeid(int)) {
std::cout << boost::any_cast<int>(p.second);
} else if (p.second.type() == typeid(double)) {
std::cout << boost::any_cast<double>(p.second);
} else if (p.second.type() == typeid(std::string)) {
std::cout << boost::any_cast<std::string>(p.second);
} else if (p.second.type() == typeid(const char*)) {
std::cout << boost::any_cast<const char*>(p.second);
} else if (p.second.type() == typeid(std::map<std::string, boost::any>)) {
show_map(
boost::any_cast<std::map<std::string, boost::any>>(p.second),
indent + 2
);
} else {
std::cout << "[unhandled type]";
}
std::cout << std::endl;
}
std::cout << std::string(indent, ' ') << "}";
This prints, for example
{
fruit: banana
taste: {
sweet: 1.0
bitter: 0.1
}
}
Unfortunately, this is hardly scalable. I'd have to add another else if clause for every type (e.g., float, size_t,...), which is why I'm not particularly happy with the solution.
Is there a way to generalize the above to more types?
One thing you can do to lessen (but not remove) the pain is to factor the type determination logic into one support function, while using static polymorphism (specifically templates) for the action to be applied to the values...
#include <iostream>
#include <boost/any.hpp>
#include <string>
struct Printer
{
std::ostream& os_;
template <typename T>
void operator()(const T& t)
{
os_ << t;
}
};
template <typename F>
void f_any(F& f, const boost::any& a)
{
if (auto p = boost::any_cast<std::string>(&a)) f(*p);
if (auto p = boost::any_cast<double>(&a)) f(*p);
if (auto p = boost::any_cast<int>(&a)) f(*p);
// whatever handling for unknown types...
}
int main()
{
boost::any anys[] = { std::string("hi"), 3.14159, 27 };
Printer printer{std::cout};
for (const auto& a : anys)
{
f_any(printer, a);
std::cout << '\n';
}
}
(With only a smidge more effort, you could have the type-specific test and dispatch done for each type in a variadic template parameter pack, simplifying that code and the hassle of maintaining the list. Or, you could just use a preprocessor macro to churn out the if-cast/dispatch statements....)
Still - if you know the set of types, a boost::variant is more appropriate and already supports similar operations (see here).
Yet another option is to "memorise" how to do specific operations - such as printing - when you create your types:
#include <iostream>
#include <boost/any.hpp>
#include <string>
#include <functional>
struct Super_Any : boost::any
{
template <typename T>
Super_Any(const T& t)
: boost::any(t),
printer_([](std::ostream& os, const boost::any& a) { os << boost::any_cast<const T&>(a); })
{ }
std::function<void(std::ostream&, const boost::any&)> printer_;
};
int main()
{
Super_Any anys[] = { std::string("hi"), 3.14159, 27 };
for (const auto& a : anys)
{
a.printer_(std::cout, a);
std::cout << '\n';
}
}
If you have many operations and want to reduce memory usage, you can have the templated constructor create and store a (abstract-base-class) pointer to a static-type-specific class deriving from an abstract interface with the operations you want to support: that way you're only adding one pointer per Super_Any object.
Since you're already using Boost you could consider boost::spirit::hold_any.
It already has pre-defined streaming operators (both operator<<() and operator>>()).
Just the embedded type must have the corresponding operator defined, but in your use context this seems to be completely safe.
Despite being in the detail namespace, hold_any is quite widespread and almost a ready-to-use boost:any substitute (e.g. Type Erasure - Part IV, Why you shouldn’t use boost::any)
A recent version of Boost is required (old versions had a broken copy assignment operator).

overloading << operator for c++ stl containers

I wish I could just print contents of a set/vector/map by using cout << . It doesn't seem so difficult for the stl designers to implement : Assuming that << is defined for T, << for a container could just iterate through the elements and print them using ofstream << .
Is there an easy way to print them that I dont know of?
If not, Is there an easy solution? I have read at places that extending stl classes is a bad idea. Is that so, and why?
how about defining an something like an overloaded print function?
EDIT:
I am looking for a recursive function which can handle containers of containers of ...
I agree that different people would like different formats, but something overridable is better than nothing
Probably the easiest way to output an STL container is
std::copy(cont.begin(), cont.end(),
std::ostream_iterator<Type>(std::cout, " "));
where Type is the type of the elements of cont (e.g. if cont is of type std::vector<int> then Type must be int).
Of course instead of std::cout you can use any ostream.
In C++11 you can use range-based for:
for (auto& i: container) cout << i << " ";
cout << endl;
The easiest eay to dump a container is probably just using std::copy(). For example I typically use something like this:
template <typename C>
std::string format(C const& c) {
std::ostringstream out;
out << "[";
if (!c.empty()) {
std::copy(c.begin(), --c.end(),
std::ostream_iterator<typename C::value_type>(out, ", "));
out << c.back();
}
out << "]";
return out.str();
}
Yes, this doesn't always work but works for my needs. This actually shows one of the problems why there is no output for containers in the standard library: there are many different ways how containers can be formatted. To make matters worse, the formatted output should be readable where thing become real fun. All of this is doable but I'm not aware of a corresponding proposal.
It doesn't seem so difficult for the stl designers to implement : Assuming that << is defined for T, << for a container could just iterate through the elements and print them using ofstream << .
Of course it is not hard for them. However, ask yourself: Does the format of the output make sense for every client? The standard library is about reuse and genericity. Coupling containers with some arbitrary output formatting rules makes them less generic for the sake of only some.
The recommended solution therefore is to provide your own operator<<(std::ostream &, T) and/or to take other generic algorithms, as found in e.g. <algorithms>.
Are you looking something like this?
#include <iostream>
#include <set>
template <typename T>
std::ostream& operator<< (std::ostream& os, const std::set<T>& s)
{
for( auto i: s ) {
os << i << " ";
}
return os;
}
Then you just may use it this way:
std::set<int> my_set = { 11, 12, 13 };
std::cout << my_set << std::endl;
Using Template template parameter makes it easy, in order to make it working for each collection you need both template<class, class...> class X and class... Args as template parameters:
template<class T, template<class, class...> class X, class... Args>
std::ostream& operator <<(std::ostream& os, const X<T, Args...>& objs) {
os << "{";
bool commoFlag = false;
for (auto const& obj : objs) {
os << (commoFlag ? ", " : "") << obj;
commoFlag = true;
}
os << "}";
return os;
}
vector<float> f_vec{ 1.3f , 5.134f, 5.78f };
list<char> c_lst{ 'F','O', 'M', 'S', 'A' };
set<int> i_st{ 17,14, -70 };
std::cout << f_vec << std::endl;
std::cout << c_lst << std::endl;
std::cout << i_st << std::endl;
output:
{1.3, 5.134, 5.78}
{F, O, M, S, A}
{-70, 14, 17}