On 2014-10-02, 1:14 AM, Xidorn Quan wrote:
On Wed, Oct 1, 2014 at 6:27 PM, Ehsan Akhgari <ehsan.akhg...@gmail.com
<mailto:ehsan.akhg...@gmail.com>> wrote:

    On 2014-10-01, 7:42 PM, L. David Baron wrote:

        On Wednesday 2014-10-01 16:24 -0700, Eric Rescorla wrote:

            Obviously, if you have some argument that auto is bad
            programming practice
            or a hazard and should thus be forbidden, that's something
            you could make
            and
            see if people generally agree...


        I think there are cases where |auto| makes code substantially less
        readable, and cases where it's fine.  I don't think I have enough
        experience reading code using |auto| to say exactly what's in which
        set, but I have mandated less use of |auto| in code reviews.

        Some of it is simple readability; there are cases where seeing the
        type of a variable allows its name to be simpler while preserving
        the same level of readability, and if we're going to hide the type,
        I'd want it to have a more complex name to make the code obvious.

        But I'm also worried about use of auto leading people to stop using
        const or & where they should be (particularly where |auto| instead
        of |const auto&| leads to unnecessary expensive copies).  (And I
        think knowing whether I want |auto| or |const auto&| requires
        knowing the type, which makes the feature less valuable to me.)

        I'm fine with just enforcing reasonable judgment in code reviews,
        although I suspect some people would be bothered by having code
        reviewers enforce style rules that aren't written down.


    FWIW, I have had some actual practical experience in using |auto| in
    the LLVM code base (and with reading code that uses it).  Here is my
    take on things:

    * Beware of using auto in cases where types can be constructed
    implicitly from other types.

    This is the most important rule, I think.  Here's an example of how
    this can introduce real bugs.  Let's imagine you have code like this:

    nsIFoo* FooGetter();
    nsCOMPtr<nsIFoo> foo = FooGetter();

    DO NOT replace the type here with auto:

    auto foo = FooGetter(); // NOT COOL!

    After this change, foo will be a raw nsIFoo*, which is a weak
    reference, so this changes the meaning of the program.

    Arguably, this is not an issue with auto, but with implicit
    conversions.  It is one of the reasons why implicit conversions are
    evil.  :-)

    * |auto| itself is rarely what you want (unless you know the
    underlying type is not copyable), you probably want |auto&| for
    references if you intend to modify the original value, or |const
    auto&| if you don't.  A sufficiently smart compiler should be able
    to figure out that it doesn't actually need to create a reference
    under the hood if the type it's seeing is a built-in one.  (clang
    seems to be able to do this based on a quick test.)

    * If you find yourself typing the type once in the statement
    already, use |auto|.  Example:

    auto ptr = static_cast<Class*>(foo);

    * Do not use auto for functions that can return different types that
    have the same interface, as it obscures away the operation performed
    on the type.  Example:

    class Container {
       // ...
       // Assume that the below iterator types map closely to the STL
    concepts
       iterator foo(int x);
       reverse_iterator foo(string y);
    };

    Container c;
    auto it = c.foo("str"); // What kind of iterator do I have?!

    * Do use auto for situations where the type doesn't really matter.
    For example, if you have code like below:

    foo(bar());

    And want to put the call to |bar| into its own statements, and do
    not care what the return type is, use auto:

    const auto& result = bar();
    foo(result);

    (Of course, depending on the nature of |foo| and |bar|, not all code
    that looks like this should be refactored this way.)

    * Do not use auto outside of a local scope.  This helps restrict the
    implications of auto to a hopefully smaller amount of code.

    * Do not overuse auto.  Consider auto as a handy tool that prevents
    you from typing needlessly.  But if you have code which uses auto
    all over the place, you're *probably* doing it wrong.

    * Remember that at the end of the day, code is read way more often
    than it is written.  If in doubt, opt for keeping the code more
    readable by typing in what you mean, IOW, don't use auto when in doubt.


I want to add one case, which is when receiving some plain integers from
some kinds of functions, and doing computation based on them. For example:

 > nsTArray<nsString> array;
 > auto length = array.Length();

In this case, the perfectly exact type of |length| should be
"nsTArray<nsString>::size_type". Before we have |auto|, the common way
is to write int32_t, uint32_t, size_t, or something similar. There are
two main problems of using those types:

1. the variable type may be different with the return type of the
function, which causes (possibly unwanted) implicit type conversion,
like converting between signed and unsigned, or 32bit and 64bit;
2. the return type may change over time, (e.g. uint32_t -> size_t),
which again causes the first problem for previously perfect code.

Hence, I suggest for cases like this, |auto| should be a recommendation.
IIRC, it is one of the cases that |auto| was introduced for.

For cases like:

 > for (int32_t i = 0; i < array.Length(); i++)

I even want to write it as

 > for (decltype(array.Length()) i = 0; i < array.Length(); i++)

but I feel it too redundant. I hope C++ could support

 > for (auto iend = array.Length(), i = 0; i < iend; i++)

but, unfortunately, it does not.

Do you think this case reasonable?

Your request is very reasonable, but as you note, it's not possible in C++. C++'s answer to this is "ranged-based for loops" <http://en.wikipedia.org/wiki/C%2B%2B11#Range-based_for_loop> which in my experience are *super* nice. They let you iterate over the array like this:

for (const auto& element : array) {
  // Use |element|
}
_______________________________________________
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform

Reply via email to