C++ Logo


Advanced search

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

From: Yehezkel Bernat <yehezkelshb_at_[hidden]>
Date: Sun, 15 Dec 2019 04:08:07 +0200
I think it was Bjarne Stroustrup who mentioned in several of his talks:
"unconstrained auto is like using void*".
I'm sure he didn't mean it from the type safety perspective, auto is still
type safe, but from the perspective of code readability, expressiveness of
the code and improving the chances of early error detection.

So "unconstrained auto" seems like the term you are looking for.


On Sun, Dec 15, 2019, 2:44 AM Martin Beeger via SG20 <sg20_at_[hidden]>

> Hello everyone!
> I recently talked a lot with coworkers about C++20 and we tried together
> to get a grasp around what its effective use is and what good coding
> guidelines around it are.
> A very fundamental change in C++20 is that Concepts are finally in (yay!).
> Concept will IMHO change how the think about template arguments and
> template function radically, and will give us the power to express
> semantic contracts much more clearly in definition. But as one uses
> concepts to modernize template functions, one quickly realizes that
> nearly all template functions either have design flaws or have
> constraints on template parameters which can be expressed by concepts.
> This lead us to the conclusion, that one should have a coding guidelines
> that flags unconstrained template parameters as a code smell. A point
> that really convinced us of that this a good rule was a simple
> challenge: Find me a well-defined template function, whose template
> parameters are truly generic (i.e. no useful requires clauses can be
> specified), and for which a test can be written that proves that it does
> as advertised for all instantiations.
> We really struggled to find one by looking though our codebase. The plus
> function came to mind, but this requires the arguments to form a magma
> at least, which is definitively a valid requires clause. The next
> candidate was the identity function, but for the identity function to be
> correct, its result must be identical to the input, which only has valid
> meaning if the input and the output is actually equality comparable,
> which is a valid requires clause.
> Se we came up for us with the "no hidden semantic requirements"-rule,
> which state that a template function should state its requirements about
> input types via concepts. If they are axioms involved, use named
> concepts to represent them. Where this leads us remains to be seen, but
> I expect the result to be far clearer code and far better
> compile-time-verification of the code.
> This brings me to auto. auto-type arguments are just template
> parameters. A completely unconstrained template parameter, to be
> precise. While I am absolutely in favor of what we call "localized
> auto", auto in cases where the lifespan is a few lines or a single scope
> (e.g. for loops, iterators, make_unique results & co.), auto in
> interfaces obscures intent and breaks the rule of "no hidden semantics
> requirements".
> So we extended the guideline to: avoid auto in interfaces in C++20,
> especially with template parameters, as there now is a clear better
> alternative: using the appropriate concept. That, unfortunately didn't
> go well.
> 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. Also it is a lot more convenient to not have to think
> about the semantics of your function and just write auto everywhere. So
> I went looking, for an cite-able reference that says: "when both apply,
> prefer concepts over almost always auto" and did not find prominent
> references about it. Does anyone have some links of reference for me I
> can cite, which clearly state, that in a C++20 world, almost always auto
> is no longer the right thing to do? Given that a well-thought out
> concept already exists and is defined, do you think we should prefer the
> concept over auto?
> But even if I manage to convince that auto in interfaces has had its
> time, but from C++20 on is a smell in new code, the next problem arises.
> If we want to have a significant motion away from auto, we must clearly
> discourage its use in interfaces. But a rule "avoid auto in interfaces"
> seemed to confuse other in practice. A lot. So I tried to figure out
> what happened. The problem was: the shorthand notion for concepts was
> "void func(ForwardIterator auto it)". From a teaching standpoint it is
> incredibly confusing that the shorthand notion, which should be
> preferred over auto, contains a semantically meaningless auto! A rule
> along the lines of "just avoid auto" is much simpler than to teach than
> a rule along the lines of "just avoid auto, except when there is this
> confusing thing which spells auto but is not really a semantic auto, as
> it will not match what auto normally matches". So a a result, this
> shorthand notion tends to be avoided out of misinterpretation of the
> guidelines, which then makes concepts unnecessarily hard to use.
> I can understand that a syntax of "void func(ForwardIterator it)" raised
> some eyebrows, but what is the reasoning behind preferring a syntax of
> "void func(ForwardIterator auto it)" over alternatives like "void
> func(concept ForwardIterator it)" or similar? Or am I missing a way to
> consistently tell this story and not confuse people?
> Has this been talked about or what is the general plan to get our
> community to move away from unconstrained template parameters and auto?
> Kind regards,
> Martin Beeger
> --
> SG20 mailing list
> SG20_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/sg20

Received on 2019-12-14 20:10:46