Reputation: 15518
Let's say Ì have some class and added output functionality by overloading the left-shift operator:
struct Foo
{
int i = 1;
std::string s = "hello";
};
auto& operator<<(std::ostream& os, Foo const& foo)
{
os<<foo.i<<"\n";
os<<foo.s<<"\n";
return os;
}
What is a good way to indent the output?
Example: If I write
std::cout<<" "<<Foo{}<<std::endl;
the output is:
1
hello
Obviously, hello
is not indented. Is there an easy way to indent the whole output (and not just the first element)?
Upvotes: 3
Views: 1271
Reputation: 8042
You can use the standard library manipulator setw
to set the width of a field, which often results in indenting the text. Here's how you use it:
cout << std::setw(10) << "Viola!" << std::endl;
This will print the word "Viola!" indented by 4 spaces. Why 4 spaces? The parameter to setw()
determines the entire width of the "field", which includes the 6 characters in "Viola!".
By default, setw()
will align the text to the right, but can be made to align left by using another manipulator left
. Here's an example:
cout << std::setw(10) << std::left << "Viola!" << std::endl;
This will output the string "Viola!" with no indentation, but with 4 spaces after it.
That should answer your original question about a good way to indent, and setw()
is not just a good way, but the standard way.
The second question asks about how to have persistent indentation, and the answer is that there is not an easy way. The easiest approach is to add the call to setw()
(or whichever indentation method that you use) in each of the calls to cout.
In addition to those answers, you should consider replacing the use of "\n" in your calls to cout
with a call to endl
. endl
is the "end of line" manipulator, and makes your code work properly with any output stream. The code would look like this:
auto& operator<<(std::ostream& os, Foo const& foo)
{
os << foo.i << std::endl;
os << foo.s << std::endl;
return os;
}
Upvotes: 0
Reputation: 3396
You're serializing the Foo
object right? So logically the serialized string of Foo
is an implementation detail of Foo
. You could write your own stream class or something along those lines but that is overengineering the problem.
auto& operator<<(std::ostream& os, Foo const& foo)
{
auto s = "\t" + std::to_string(foo.i) + "\n"
"\t" + foo.s;
return (os << s);
}
int main()
{
std::cout << Foo{} << "\n";
}
Upvotes: 1