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

Marc Mutz marc.mutz at kdab.com
Tue Dec 22 15:50:30 CET 2015


On Tuesday 22 December 2015 13:42:06 Ziller Eike wrote:
> > On Dec 22, 2015, at 1:28 PM, Marc Mutz <marc.mutz at kdab.com> wrote:
> > 
> > On Tuesday 22 December 2015 11:26:40 Ziller Eike wrote:
> >> We have something similar in Qt:
> >>    QString a = "ABC";
> >>    QString b = "abc";
> >>    auto result = a + b;
> >>    a.replace("A", "C");
> >>    qDebug() << result;
> >> 
> >> prints “CBCabc” instead of “ABCabc” when QT_USE_FAST_OPERATOR_PLUS is
> >> defined, because result is not a QString in that case.
> >> 
> >> So funny/unwanted behavior can occur both because one used the wrong
> >> explicit type, and because one used auto instead of an explicit type.
> > 
> > This is not specific to auto, though:
> >    QStringView v = QLatin1Char('a');
> >    const char *data = str.toLatin1(); // implicit conversion by default
> >    QLatin1String l1 = str.toLatin1();
> >    QVector<int> v = {0, 1, 2};
> >    QVector<int>::iterator it = v.begin();
> >    const QVector<int> v2 = v;
> >    *it = 1;
> >    assert(v2.front() == 0); // boom
> > 
> > It's a general peril when working with C++.
> 
> I’m actually not arguing against the use of auto in principle. But I’m
> arguing against introducing auto because it (supposedly?) makes the code
> safe(r). (That context has unfortunately been cut off from the mail at
> some point.) C++ is complicated, and type deduction and its results are no
> exception. If you know what you are doing, auto can make code more
> readable and easier to write, especially with templated code. When it
> makes code more readable or not tends to be pretty subjective it seems, so
> IMO someone just has to decide :)
> 
> > Reminds me of the 1970s when we got a law requiring the use of the
> > seat-belt in cars in Germany. My uncle used to tell the story how one of
> > his friends survived a crash because he was ejected from the car since
> > he was _not_ buckled up, just to follow up with the story how another
> > friend was not harmed in a crash because he _was_ strapped in...
> 
> Not sure what you want to say with this analogy.
> Anyhow, discussions about pros and cons are still necessary. I’m sure that
> there are laws in Germany that supposedly increase security but
> effectively don’t. I would require that the decision to introduce a law
> requiring the use of seat-belts was based on extensive studies on how seat
> belts increase or decrease the security of a car’s occupants, and how they
> need to be designed to achieve that best. And not on stories at the bar,
> of how one or the other person was either saved or doomed by a seat belt,
> which you seem to be reminded of by the discussion here? ;)

It was just a story I was reminded of, but if you want an interpretation:

It's a reminder about how progress always needs to overcome the status quo. 
And about how humans rate personal experience (first hand, or perceived through 
third parties) higher than statistics.

You can see it over and over again here:

QList is a mistake, but people will try to find ways to argue that it's useful 
because they have this one contrieved use-case where it outperforms vector:

   struct payload { char data[1024]; };
   QList<payload> l(10000);
   l.pop_front();

, say.

nullptr is obviously a better alternative than 0 or NULL, but people argue 
that there's this one corner of the huge C++ design space where nullptr 
doesn't add value over 0. Why should I learn a complicated rule if there's a 
simple one: always use nullptr?

Adding const to local variables is very important in a world of implicitly-
shared types, you can see the asm getting simpler, sometimes radically so, by 
just adding const when it avoids detaches, but people deny adding const as a 
drive-by and disallow commits that just add const without some kind of 
performance analysis).

I don't know whether auto creates more harm than it fixes. What I _do_ know is 
that it makes it much easier to write efficient code, because you _do_ think 
twice whether to submit something like

    for (QHash<QLongTypeName, QEvenLongerTypeName>::const_iterator
         it = m_veryExpressiveName.constBegin(),
         end = m_veryExpressiveName.constEnd();
         it != end; ++it)

as a replacement of

    foreach(const QLongTypeName &key, m_veryExpressiveName.keys()) {
        const QEvenLongerTypeName &value = m_veryExpressiveName.value(key);

but not if you can say

    for (auto it = m_veryExpressiveName.cbegin(), end = 
m_veryExpressiveName.cend(); it != end; ++it)

(yes, this use is uncontended, but this one isn't:

    foreach(const QString &s : someLongExpression()->fooBar().names())

    const auto strings = someLongExpression()->fooBar().names();
    for (const QString &s : strings)

, but is essentially the same).

Thanks,
Marc

-- 
Marc Mutz <marc.mutz at kdab.com> | Senior Software Engineer
KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company
Tel: +49-30-521325470
KDAB - The Qt Experts



More information about the Development mailing list