I have a class T
which has a map of string
class T
For convinience, I would like to print the content in the class in an organized manner with tabulations.
As an example, I have:
#include <iostream>
#include <map>
#include <string>
class test;
typedef std::map<std::string, std::string> sMap;
typedef std::map<std::string, test> testMap;
class test {
public:
sMap map1;
testMap map2;
};
std::ostream& operator<<(std::ostream& os, const sMap& smap) {
for(const auto& s_smap : smap) {
os << s_smap.first
<< "\t"
<< s_smap.second
<< "\n";
}
return os;
}
std::ostream& operator<<(std::ostream& os, const test& t) {
os << t.map1
<< "\n";
for (const auto& s_map : t.map2) {
os << s_map.first
<< "\t"
<< s_map.second
<< std::endl;
}
return os;
}
int main() {
sMap myMap;
myMap["a"] = "b";
test obj;
obj.map1 = myMap;
test obj2;
obj2.map2.insert({"one", obj});
obj2.map2["one"].map2.insert({"two", obj});
obj2.map2["one"].map2["two"].map2.insert({"three", obj});
obj2.map2["one"].map2["two"].map2["three"].map2.insert({"four", obj});
std::cout << obj2 << std::endl;
return 0;
}
I would like the output to be:
one a b
two a b
three a b
four a b
How can the operator<<
be overloaded to achieve this?
CodePudding user response:
Doing this means you need to pass along extra information. You could create a printMap
kind of fucntion that takes an indentation level as an argument, but you've said you want to achieve this by overloading operator<<
so you can't pass that along unless you wrap your test
objects in another class/struct that does carry that info.
That might look something like the below, which outputs:
% ./a.out
a b
a b
a b
a b
Tweaking this is left as an exercise for the OP.
#include <iostream>
#include <map>
#include <string>
struct test;
using sMap = std::map<std::string, std::string>;
using testMap = std::map<std::string, test>;
struct test {
sMap map1;
testMap map2;
};
struct indent {
const test &ref;
int indentLevel;
indent(const test &ref, int indentLevel=0)
: ref(ref), indentLevel(indentLevel)
{ }
};
std::ostream& operator<<(std::ostream& os, const indent &i) {
int j = i.indentLevel;
for (const auto &[f, s] : i.ref.map1) {
for (int k = 0; k < j; k ) os << "\t";
os << f << "\t" << s << "\n";
}
for (const auto &[f, s] : i.ref.map2) {
os << indent(s, j 1);
}
return os;
}
std::ostream& operator<<(std::ostream& os, const sMap& smap) {
for (const auto &[f, s] : smap) {
os << f << "\t" << s << "\n";
}
return os;
}
std::ostream& operator<<(std::ostream& os, const test& t) {
os << t.map1
<< "\n";
for (const auto& s_map : t.map2) {
os << s_map.first
<< "\t"
<< s_map.second
<< std::endl;
}
return os;
}
int main() {
sMap myMap;
myMap["a"] = "b";
test obj;
obj.map1 = myMap;
test obj2;
obj2.map2.insert({"one", obj});
obj2.map2["one"].map2.insert({"two", obj});
obj2.map2["one"].map2["two"].map2.insert({"three", obj});
obj2.map2["one"].map2["two"].map2["three"].map2.insert({"four", obj});
std::cout << indent(obj2) << std::endl;
return 0;
}
Some aspects of this case incorporate post-C 11 features like structured bindings. If a newer standard cannot be used, these techniques can be converted to C 11 friendly constructs.