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:

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