[Qt-interest] Semi-OT: indentation with operator<<

K. Frank kfrank29.c at gmail.com
Mon Aug 2 15:57:32 CEST 2010


Hello Andre -

Thank you for the additional improvements.  I like it.

On Mon, Aug 2, 2010 at 2:03 AM, Andre Somers <andre at familiesomers.nl> wrote:
> Op 2-8-2010 2:14, K. Frank schreef:
>> Hello Andre -
>>
>> Thanks for your refinement.
>>> ...
>>> If you want, you could wrap it up into a RAII class, so you can not
>>> forget about it and early exits and the likes are automatically handled.
>>> That might make it slightly cleaner to work with, perhaps.
>>> ...
>> I think I follow what you are saying.  To make it concrete, let
>> me add the static variable you mention and refer back to my
>> example:
>>
>> class Indenter {
>>    public:
>>      Indenter() {++indentation_level;}
>>      ~Indenter() {--indentation_level;}
>>      static int level() {return indentation_level;}
>>      static int indentation_level = 0;
>> }
>>
> Something like that, but I would make the indentation_level private, and
> level() non static.

Okay, makes sense.

> Also, I think you can not initialize like that.
> AFAIK, you need to initialize from an implementation file somewhere.

Yes, this is correct.  I was cheating a little to make the example
more readable.  (I wish they'd change this, though.)

> I would initialize to -1, read on for the why. Also, as a helper funtion,
> perhaps you should make the indenter itself streamable, so you get rid
> of the for loops everywhere else. That will clean up your code a *lot*:

I especially like this idea of defining op<< for Indenter.  Very clean.

>> ...
> Note quite, I'd say.
> If you initialize to -1 and make the indenter streamable, you can
> rewrite it to something like this:
>
> // Indenter-based implementation, version 2
>
> std::ostream&  operator<<  (std::ostream&  o, MoreStuff const&  m) {
>   Indenter indent;<-- constructor increments indentation_level. Initial use will yield 0.
>   o<<  indent<<   "double1_   =  "<<  m.double1_<<   "\n";
>   o<<  indent<<   "point3d_   =  "<<  m.point3d_<<   "\n";
>   o<<  indent<<  "someStuff_ = ...\n";
>
>   o<<  someStuff_;
>   return o;
>
>   // Indenter indent goes out of scope and gets decreased automatically.
> }

Looks good.

> That is, in *all* your classes that should work with an indent, start with constructing the Indenter instance. Best not to call it i, as i is kind of reserved for loop counters so that may be confusing. In your small piece of code, you already use i like that too!

Indeed.  After all, variables with names beginning with the letters
'I' through 'N' are automatically typed as integers.  Oh, wait, that's
not the case anymore -- that's a ghost from the steam-powered era.

> If you initialize Indenter::indentation_level to -1, the first use will yield you a level 0. Making level() non-static will make sure you don't forget to create an instance before using it. In the class implementation for someStuff_, you do the same, so it will be indented at a higher level. If you ever decide to put MoreStuff itself inside another class or struct that you want to ouput in the same way, you don't need to change anything. Just implement EvenMoreStuff's stream operator in the same way, and your indenter will just work correctly.
>
> If your create a stream implementation for Indenter itself, your code will look much cleaner as you can see above (and there will be less of it, so less chances for mistakes).
>
>> Makes sense to me.
>>
> I hope the version above makes even more sense to you. :-)

Indeed it does.  Thanks.

Now all we need to do is petition to make this QIndenter...

(Just kidding, but I'm trying to make this thread on-topic somehow.)

> André

Thanks for everyone's indulgence.


K. Frank




More information about the Qt-interest-old mailing list