Also, another solution is to make a function called to_string
for example (this is to directly convert your struct to string, but the performance is not good)
struct A
{
int a0;
string a1;
bool a2;
string to_string() const {
return "{ " + std::to_string(a0) + ", " + a1 + ", " + (a2 ? "true" : "false") + " }";
}
};
Then
template<typename T>
void print(const T &a) {
cout << a.to_string() << "\n";
}
This is not good for printing, for printing, use the C++ convention of implementing operator<<
But.
This have a disadvantage, when an subclass want to change the output format. It can't.
So
class DynamicallyToStringConvertible {
public:
virtual string to_string() const = 0;
virtual ~DynamicallyToStringConvertible() {}
};
struct A: DynamicallyToStringConvertible
{
...
virtual string to_string() const {
return "{ " + std::to_string(a0) + ", " + a1 + ", " + (a2 ? "true" : "false") + " }";
}
}
struct SubclassFromA: public A {
virtual string to_string() const {
return "Subclass: " + A::to_string();
}
};
The function print
is as is
Then
void tryPrintingAsA(const A &a) {
print(a);
}
You will find now (after virtual functions), this will work for SubclassA.
But if you tried the operator<<
or the beginning of the solution (to_string without virtual), it will work for SubclassA as it was a vanilla A.
Then you would make something like that
friend ostream &operator<<(ostream &s, const DynamicallyToStringConvertible &p) {
return s << p.to_string();
}
Inside your Base class, like this:
class DynamicallyToStringConvertible {
public:
virtual string to_string() const = 0;
virtual ~DynamicallyToStringConvertible() {}
friend ostream &operator<<(ostream &s, const DynamicallyToStringConvertible &p) {
return s << p.to_string();
}
};
Now try the printing function for A to be:
void tryPrintingAsA(const A &a) {
cout << a;
}