I’m open to auto, but skeptical.

(1) Research-ability. I read a lot of code that is new to me, that I have never 
written. I find type statements to be useful as documentation for where to look 
for more information about how data structures and algorithms relate to each 
other. Traversing a tree or list of data structures by type name while reading 
code is a common task for me. But I can’t select and search for auto, auto*, or 
auto&.

(2) Mechanics. It’s totally true that if you loop over one collection and put 
the values into another collection, subject to some filter, the types involved 
aren’t really interesting to reviewing the filter. But if you want to review 
low-level mechanics like object lifetime and thread safety, suddenly the types 
are really important. I think the “I changed RefPtr to auto and then crashed” 
examples in this thread are about mechanics.

I find it strange that, as JavaScript authors adopt tools like TypeScript 
because they find type-less programming to be unmaintainable, C++ authors move 
toward type-less programming. Perhaps the grass is always greener on the other 
side. Or perhaps we can strike a balance and put types where they help us.

Two arguments made in favor of auto don’t fully convince me:

(1) You were always able to hide the types of certain expressions. 

I’m hoping the point of this argument is not to say “in for a penny, in for a 
pound”, but rather to raise our awareness that we’ve been OK with certain 
type-less expressions all along. I agree: I'm OK with hiding types in some 
places, especially if surrounding code already provides some kind of type 
foothold.

At the same time, I sometimes break expressions into statements to improve 
clarity and research-ability or to achieve certain mechanics.

Maybe this answers Darin’s question:

> Here’s one thing to consider: Why is it important to see the type of 
> foundSource->value, but not important to see the type of shifts.take(source)? 
> In both cases they need to be Vector<ShufflePair>.

In the cited code, ‘shifts’ is declared as HashMap<Arg, Vector<ShufflePair>>, 
and HashMap ’take' is well understood to return its value type, so no further 
comment about type is necessary for me on this line.

Following this logic, I might be OK with eliding the type of 
foundSource->value. But we’re starting to reach a limit. Each time we do this 
we create an auto link in the type chain. If I have to trace back three autos 
deep in order to understand a type, I’m gonna have a bad time. Each type 
declaration is a stopping point for research. Therefore, I don’t prefer the 
fully auto version of this code.

Following this logic, I would be OK with const auto& a little later in this 
algorithm:

>             bool isRotate = false;
>             for (const ShufflePair& pair : currentPairs) {
>                 if (pair.dst() == originalSrc) {
>                     isRotate = true;
>                     break;
>                 }
>             }

Might as well use const auto& for ‘pair’: The type of currentPairs is 
well-documented locally. If currentPairs were a data member, and not declared 
in the same screenful of code, I would want to write out a type for ‘pair’. 
Otherwise, I would have to open another file to understand this line.

But somebody said we don’t like const auto&? Is this a gotcha somehow?

(2) You can’t be sure of the stated type, since a type conversion may have 
happened.

Knowing that a value is equivalent to a certain type still provides a foothold 
for research and understanding mechanics.

We only allow automatic type conversion when we consider types to be reasonably 
equivalent. We consider it bad style to convert willy-nilly, and we use the 
explicit keyword to avoid errant conversions. For example, we don’t allow 
RefPtr to automatically convert to raw pointer.

Geoff
_______________________________________________
webkit-dev mailing list
webkit-dev@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-dev

Reply via email to