C++ Logo

sg20

Advanced search

Re: [SG20] Difficulties in teaching the use of C++20 concepts

From: Martin Beeger <martin.beeger_at_[hidden]>
Date: Sun, 15 Dec 2019 14:56:28 +0100
Hallo Herb!

Am 15.12.19 um 06:45 schrieb Herb Sutter:
>
> > The C++ Committee Members like Herb Sutter have preached "Almost always
>
> > auto" for almost a decade, and so our guidelines seems to oppose that
>
> > C++ guru wisdom.
>
> Thanks! FWIW, my AAA advice from 2013/14 continues to be widely
> misunderstood in three ways:
>
> 1. I’ve never ruled out concept constraints, and since the beginning
> of AAA in 2013 I've pointed forward to concept-constrained auto a
> number of times (see example reference at bottom). As soon as we have
> concepts, we should write concepts -- that's just a constrained auto.
> That is,
>
>                 auto first = vec.begin();
>
> should naturally be upgraded to
>
>                 iterator auto first = vec.begin();
>
> which is still auto, just constrained. In fact, I expect (hope) that
> this availability of concept constraints on auto variables will bridge
> much of the remaining disconnect/debate about whether to use auto
> regularly or not, because it gives people the ability to still express
> constraints on the type of the variable, while still getting the
> benefits of auto (generality, consistency, no-conversion guarantee,
> initialization guarantee, not needing to commit to a concrete type
> [but see #2], and so on).
>
As I stated in Arthurs mail, this is exactly the point I was missing.
Although watching Bjarnes talk where he proposed Integer a = ... with
integer being a concept, not a type, I did not know that this syntax
actually made it through. If concepts can be applied consistently to
constrain any use case of auto, whether it is template in function
specification, or a auto-deduced type in a statement, this solves all
the things I was talking about. The story now just is: if you like auto,
fine, but think about constraining it if you don't already have it
pinned down to a type.
>
> 2. I don't teach to always deduce a type. There are two forms I've
> always taught:
>
>                 auto x = expr;    // to make the type track, deduce it
>
>                 auto x = type{expr};        // to make the type stick,
> commit to it
>
> both of which are still auto. So although the first form is great for
> making code less brittle under maintenance including to avoid
> introducing silent conversions/temporaries as types change, the second
> form is still always available (and actively recommended) when it's
> appropriate to commit to a particular type, and "AAA" has always
> taught both of these styles.
>
> However, note that the advice to use concepts constraints applies only
> to the first form, which is deduced. It’s not very useful in the
> second form, which already commits to a concrete type.
>
Immediately deduced types, as in the second example have a much stronger
commitment so to speak, they are not only bound to a concept, but even
to a type. I totally agree that these should be treated as a different
form of auto.

When we program, we tend to think in patterns, not in details. I do
understood AAA as an attempt to write code closer to our mental model
and not to pin down your code to include unnecessary requirements which
are not essential to the correctness of your code. If you thougth about
a loop which contains a correct algorithm for a wide range of types, and
you then write

for(int value: mMyVector)

the information  that this loop is not only correct for integers, but
for a far wider range of types is lost. AAA should encourage you to
avoid this information loss.

A lot of the criticism of this AAA comes up from the fact, that while
int was a way specific, auto in some cases might be too brittle, as it
leads to code compiling, even when semantics contracts are violated. I
myself was sceptical about AAA just because I considered being too
specific and having the compiler tell me and having to re-think and
rewrite the code less of a problem than debugging the accidentally
compiling code which does not do what I think it does anymore.

The concepts feature for auto now removes the black and white from this
decision, it is possible to meet int the middle and express the
programmers intent. If I think my loop is only valid for all kinds of
integers, I can write

for(integer auto value: myVector)

if I think its valid for all kinds of regular types, I can do sth. along
the lines of:

for(regular auto value: myVector)

While we had valid discussions about which hill to die on (over- oder
unconstrained), there should be much more consent if there is a option
to not die at all on the table.

> 3. The "Almost" in "Almost Always Auto" is now largely gone thanks to
> C++17 guaranteed copy elision -- so these days the idiom should be
> renamed pretty much "Always Auto," though of course people are as
> always free to disagree.
>
> > Does anyone have some links of reference for me I can cite
>
> I would suggest these two:
>
> * My CppCon 2014 talk, starting at 30:00
> <https://youtu.be/xnqTKD8uD64?t=1807> where the very first point
> highlighted in the AAA section was point #2 above that there are
> two forms and AAA does not mean always deducing the type (so I
> wish people wouldn’t forget that there are the two forms, but oh
> well).
> * My 2013 article GotW #94
> <https://herbsutter.com/2013/08/12/gotw-94-solution-aaa-style-almost-always-auto/>
> which was the first time I think I talked about AAA.
>
I knew those, these refer to a pre-C++20 world, I was looking for advice
in a post-C++20 world.
>
> I think both of them say the things you are asking for. For example,
> the article mentions concepts in passing, then I wrote in the Q&A in
> the comment section:
>
> As I wrote on the Reddit thread: Second, a huge amount of the
> discussion in this thread is of the form “but if we had concepts we
> would write “Conceptname x = …;”. That’s exactly true and I’m one of
> the ones pushing strongest for that — and it’s a reason to use “auto x
> = …;” today because it will mean the same thing, namely to deduce the
> type (not specify it exactly, no conversions, etc.), just adding the
> ability to check that the deduced type matches the concept. This is a
> direct (and intended) evolution of declaring with auto per AAA. If you
> like that, you’re in good company, and you should use auto today.
> Telling people to declare with concrete types today is not at all the
> same thing and puts you on a different path of committing to concrete
> types, which is the opposite of “Conceptname x = …;”.
>
> which is what I think you’re looking for?
>
I favor dying on the overconstrained hill today, as I can easily break
and fix my code to be less constrained on demand, as dying on the
underconstrained hilll (semantically broken code compiles) hill, as this
is hard to find out for me. So I get you, but I will not walk this path
in the meantime.

But to sum up regarding the use of auto, a post-C++20 guideline could be
(a hopefully much more well-formulated and littered with examples
version of the following):

1. whenever the type of the expression is mentioned on the right hand of
a statement, just put auto on the left side for brevity instead of
repeating yourself on the left hand.

2. whenever auto represents a generic value whose type is not known
locally, look for a fitting named constrained and apply it for the auto
parameter to ensure semantic correctness of the using code without loss
of genericity.

3. whenever you develop code and you are not thinking of its correctness
in terms of concrete types but in form of general concepts, use auto.

4. whenever you write functions, try to think of the problem in you
solve as a abstract problem and about generic solutions, not only about
one for your concrete types. Look for an exisisting solution to a
general problem.

As you apply the last rule to your coding (in line with Sean Parents
Better Code principles) you will either find an a solution already
there, if you don't, what you will write will now fall under rule 3,
which will in turn then fall under rule 2.

Is that an accurate representation of what the your AAA (now AA) rule
intends to achieve and how you would advise in a C++20 world?

I as and AAA skeptic can totally get behind this new version.

Martin


Received on 2019-12-15 07:58:57