[Development] RFC: more liberal 'auto' rules?

Matthew Woehlke mwoehlke.floss at gmail.com
Sat Dec 5 00:10:45 CET 2015

On 2015-12-04 17:43, André Pönitz wrote:
> On Fri, Dec 04, 2015 at 04:33:26PM -0500, Matthew Woehlke wrote:
>> Which of these is easier to read? (More importantly, which is easier to
>> *verify* that it is correct?)
>>   for (int i = 0; i < list.size(); ++i)
>>     foo(list[i]);
> Whether the access is correct depends on the type of list, which you don't
> disclose.

That's sort of *the point*. I can't tell if the above is correct or not.
If it used 'auto', I'd know.

(And it's sort of implied that it *is* wrong. Because, y'know, I see
loops like the above quite often where, indeed, they do in fact use the
wrong type. Actually, QList/QVector are about the *only* times the above
is written correctly without using 'auto'. More often than not, a loop
like that written against a non-Qt container uses the wrong index type.)

> In any case, this loop follows a well-known pattern.

It also follows a really *bad* pattern. The count is reevaluated every
time (well, you hope the compiler will hoist it, but the code says that
it is). Using type deduction... well, sucks:

  for (auto i = decltype(list.size()){0}; i < list.size(); ++i)

>>   for (auto i : qtIndexRange(list.size())
>>     foo(list[i]);
> In any case, this is an uncommon pattern, using some unknown qtIndexRange()
> function.


  for i in range(len(list))

Just because it isn't standardized (or in Qt) yet doesn't mean it's
"unheard of". It's just that C++ users have been suffering with the
difficult to use form while programmers in other languages have had the
much more sensible form for a long time.

Really, it's not hard... nasty glorified while loop vs. 'I want to
iterate over the indices [starting at zero] up to list.size()'.

There's a reason I strongly prefer the latter form and use it whenever I
can (usually subject to compiler compatibility limitations).

> Moreover it is more to type.


  for (auto i : qtIn<tab>list.si<tab>))
     - vs. -
  for (int i = 0; i < list.si<tab>; ++i)

Hey, look... mine's *fewer* keystrokes. And much more importantly, it's
*correct*. Yours... may or may not be... as you pointed out, I don't
know without knowing decltype(list). (Or I could use the much longer,
*much* uglier old-style for loop with decltype that is correct, but then
mine wins hands-down.)

> The extra level of parantheses makes it harder to parse for
> humans,introducing an aditional source of errors, which you nicely
> demonstrated by making the example non-compilable.

Bah. A decent IDE would have flagged that as soon as I stopped typing.
(Actually, a decent *text editor* would have shown me () matches, so I
would have noticed *as* I was typing. I challenge you to write bug-free
code the first time in a text editor whose most advanced feature is cut
and paste.)

>> Which is *really* more meaningful?
> The first one.

Sorry, but I must strongly disagree.

>> "The type of 'i' is 'int', and I
>> really, really hope that 'list' is actually indexed by 'int'", or "the
>> type of 'i' is the index type of 'list'¹"?
>> Do you really *care* what is the type of 'i'?
> Yes, I do care about types, almost always.

Why? As long as it's the *correct* type, what difference did it make?

Let's say that the correct type is my_list::index_t. Let's say I used that:

  for (my_list::index_t i = 0; i < list.size(); ++i)

How is that better? Do you know now what is the actual type of 'i'?

I submit that writing 'my_list::index_t' is not a significant
improvement over 'auto'. It didn't tell you anything about the actual
type of 'i'. (It does suggest that the type of 'list' might be 'my_list'
and that a 'my_list' probably uses 'my_list::index_t' as its indexing
type. But there's still that "probably". Whereas 'auto' says the type
*is* the indexing type.)

> Your message has been heard. I do not agree with you.


> I feel more comfortable arguing about whether a type is the right one
> if the type is known than when it is unknown.

Then you are missing the point. In fact, you are missing the whole point
of 'auto'. By using 'auto' correctly, it's possible to know that the
type *is correct*, even if you don't know what the type actually *is*.
(Or if a change elsewhere should change what is the correct type.)


More information about the Development mailing list