The madness called "simple concepts syntax"

487 views
Skip to first unread message

mihailn...@gmail.com

unread,
Jun 19, 2018, 5:33:54 AM6/19/18
to ISO C++ Standard - Future Proposals
OK, right now in flight are about FOUR proposals, trying to "simplify" and "make more clear" concepts usage.

This is madness. It is madness, because NONE of it make it more clear! None. 

By inviting new language constructs one does not make things "more clear", it only adds more things to learn.

The worst part is - we have working solution that is clear. Granted verbose, but clear. 

If one makes it Not verbose but Not clear (not self-explanatory, need learning) also one gains nothing! 


Consider

template<Iterator Iter1, Iterator Iter2> 
     requires Comparable_though_iterators<Iter1, Iter2>
bool equal(Iter1 first, Iter1 last, Iter2) 
{} 

This code is clear to ANYONE who EVER worked with C++, even to a time traveler from 30 years ago!

Comparable_through_iterators{Iter1,Iter2} 
bool equal(Iter1 first, Iter1 last, Iter2) 
{} 

This is NOT clear

First Comparable_ can be confused with a return type when one starts to read. 
Second The syntax is COMPLETELY alien to templates - de facto new language. 
Third there is no obvious connection b/w the function and the clause  - it just sits there like a separate declaration
Forth Automatic names introductions is very uncommon and will be confusing for sure.

The gain of one-less-line is DWARFED by the HEAP of "new stuff" that does NOT grant "new powers"!


 --- Let's continue


Between 

void sort(Sortable& s);  

and

template void sort(Sortable& s); 

The second is more confusing! Why? Because it abuses an already established syntax for something completely different. 

Is the first confusing? Might be. What is the solution?

Solution 1:

If this is your code, and you might be confused - don't use it, use the more verbose, but more clear syntax!

Solution 2:

Just ctrl-click on Sortable (hell, just hover over it) and all you doubts will be solved! 


Inventing completely new syntax in the form of  Sortable{} is even worse:

Consider 

Number x{};
[](Number{} x) 
{}
[x = Number{}]()
{} 

Again, any gains are dwarfed by introducing new syntax to learn and/or new ways to read old constructs! 
And the biggest problem is - that syntax right now donates an action and here it will not, it will be just an indicator! 


 --- Let's continue further

Another non-issue is "the problem one cannot differentiate b/w constrained value and a type concept" 

template<Concept T, Value v> void f() {}

Why this is non-issue? 

First Because templates are inline, usage is visible and Types and Value are used RADICALLY differently.
In real word it will always be clear which is which! 

Second as already mentioned in one of the papers - one can use a naming convection.

Third the more verbose syntax (the a requires clause) is still available! 

And BTW lets not forget we have class template arguments now, so the template arguments are bound to be a bit overloaded now!

template<Concept T, Value v, Class c> void f() {}

Nothing wrong with that - we can use naming conventions and we have good IDEs to help us - no need for syntax noise.  


The Solution To All This


For now, include only the syntax clear to a time traveler! Do not include ANYTHING new to learn! 

We are JUST introducing Concepts to the general public - that alone is enough new  material!

For Simple cases

template<Sortable S> 
void sort(S& s); 

For Complex cases

template<Iterator Iter1, Iterator Iter2> 
     requires Comparable_though_iterators<Iter1, Iter2>
bool equal(Iter1 first, Iter1 last, Iter2) 
{} 

      THATS IT. DONE. 

No
template void sort(Sortable& s); 

No
void sort(Sortable{}& s); 

No 
template<Arithmetic{N}, Arithmetic {} n> void f(N);

No
template<auto Arithmetic N> void f();

No
template<Comparable_through_iterators{Iter1,Iter2}>
bool equal(Iter1 first, Iter1 last, Iter2) 
{} 

And HELL No
Comparable_through_iterators{Iter1,Iter2} 
bool equal(Iter1 first, Iter1 last, Iter2) 
{} 

Why?

A. Because of the time traveler!!!

B. Let the users have theirs say IN THE REAL WORD.

C. We can ALWAYS add "simpler" syntax later, say in 5 years!


Future Directions

Why not let arguments be comma separated lists if we care so much about typing

template<class In1, In2, Out> 
   requires Mergeable<In1, In2, Out>  
Out merge(In1,In1,In2,In2,Out);

Why not instead of the new syntax for names introducing we simply

requires Mergeable<In1, In2, Out>  
Out merge(In1,In1,In2,In2,Out);





floria...@gmail.com

unread,
Jun 19, 2018, 5:54:51 AM6/19/18
to ISO C++ Standard - Future Proposals
I mostly agree with you. I don't think a "terse" syntax is needed.

However, let's not forget something: if you cannot read/write C++ without an IDE, then C++ has got too complex for any human being. So I strongly disagree with your "ctrl-click" argument.
There are many cases where we need to read code and cannot ask an IDE (because it's a single file extracted from the project like in an email for instance).

mihailn...@gmail.com

unread,
Jun 19, 2018, 8:29:38 AM6/19/18
to ISO C++ Standard - Future Proposals, floria...@gmail.com


On Tuesday, June 19, 2018 at 12:54:51 PM UTC+3, floria...@gmail.com wrote:
I mostly agree with you. I don't think a "terse" syntax is needed.

However, let's not forget something: if you cannot read/write C++ without an IDE, then C++ has got too complex for any human being. So I strongly disagree with your "ctrl-click" argument. 
There are many cases where we need to read code and cannot ask an IDE (because it's a single file extracted from the project like in an email for instance).


Honest question. Are there any case syntax is added for humans only? I can think of many places where it is removed (auto, for(:), etc ect), but not a single case where it is added


In any case, names meaning potentially multiple things is nothing new. Variables and constants are prime example - scope local, function static, function argument, static, member, template non-type argument. 

We use both tools and naming conventions to aid us.

template<Container C, Integer i, Class c>
void f() 
{}

This is the natural upgrade to
  
template<class C, int i>
void f(Class c) 
{}

that the time traveler will have no problems with. 

floria...@gmail.com

unread,
Jun 19, 2018, 8:47:47 AM6/19/18
to ISO C++ Standard - Future Proposals


Le mardi 19 juin 2018 14:29:38 UTC+2, mihailn...@gmail.com a écrit :


On Tuesday, June 19, 2018 at 12:54:51 PM UTC+3, floria...@gmail.com wrote:
I mostly agree with you. I don't think a "terse" syntax is needed.

However, let's not forget something: if you cannot read/write C++ without an IDE, then C++ has got too complex for any human being. So I strongly disagree with your "ctrl-click" argument. 
There are many cases where we need to read code and cannot ask an IDE (because it's a single file extracted from the project like in an email for instance).


Honest question. Are there any case syntax is added for humans only? I can think of many places where it is removed (auto, for(:), etc ect), but not a single case where it is added

You over-interpreted what I said. And all your examples are primarily for humans.
What is the most understandable for a human:
std::vector<int> vec;
for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
 
int& i = *it;
 
/* do some stuff with i */
}
or
std::vector<int> vec;
for(auto& i : vec) {
 
/* do some stuff with i */
}
?

Obviously, most people find the second one easier to read/write. And they absolutely don't an IDE for that.
Your "ctrl-click" argument transposed to this loop example would be to say we could have an IDE that has an option to generate the first loop when clicked on a container variable, so we don't need this fancy range-based for-loop.
At least, that's how I see your "ctrl-click" argument.

But don't get me wrong, I fully agree with your time-traveler argument.

Hyman Rosen

unread,
Jun 19, 2018, 10:41:23 AM6/19/18
to std-pr...@isocpp.org
On Tue, Jun 19, 2018 at 5:33 AM <mihailn...@gmail.com> wrote:
OK, right now in flight are about FOUR proposals, trying to "simplify" and "make more clear" concepts usage.
This is madness. It is madness, because NONE of it make it more clear! None. 

I agree with you, but I think there's one piece of new syntax that is OK.
To wit:

For Simple cases
template<Sortable S> 
void sort(S& s);

I don't like this.  I think it overlaps too much with non-type parameters.  I would prefer

void sort(auto<Sortable>& s);

1) The angle brackets signal that templates are involved.
2) The auto signals that the compiler is deducing something.
3) The keyword followed by a name in angle brackets signal that
something is being constrained; it almost has the feeling of a cast.

Nicol Bolas

unread,
Jun 19, 2018, 10:49:49 AM6/19/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com


On Tuesday, June 19, 2018 at 5:33:54 AM UTC-4, mihailn...@gmail.com wrote:
OK, right now in flight are about FOUR proposals, trying to "simplify" and "make more clear" concepts usage.

This is madness. It is madness, because NONE of it make it more clear! None. 

By inviting new language constructs one does not make things "more clear", it only adds more things to learn.

The worst part is - we have working solution that is clear. Granted verbose, but clear. 

If one makes it Not verbose but Not clear (not self-explanatory, need learning) also one gains nothing!

Clarity is ultimately a measure of time. Variadic templates are not "clear" to people who've never seen them. UDLs are not "clear" to people who've never seen them. Lambdas are not "clear" to people who've never seen them. Structured bindings are not "clear" to people who've never seen them. And God knows rvalue references and forwarding references would utterly baffle people who've never seen them.

All of these things are clear to us now because we are used to them. That's the only reason why they are clear. Your hypothetical time traveler from the C++98/03 days would be confused by the simplest of modern C++11 code.

And that's OK.

Saying that a syntax is wrong just because we're not used to it is not helpful. It's far more useful to look at things from a cost/benefit analysis.

Lambdas are probably the best example, because they don't do anything that you couldn't do yourself, either with in-situ struct declarations or out-of-function declarations. So their benefit is purely convenience.

Lambdas have a huge syntactic cost. They have novel introduction syntax, re-appropriating something that looks like an array into a function/class declaration. They are functions that can be declared without parameters, without even `()`. They deduce the return value unless you specify otherwise. They allow `auto` in parameter lists. They can capture values/expressions in a myriad of ways. And so forth.

All of this represents a syntactic variance relative to regular functions. And thus, it is a burden, a cost for entry that people have to learn.

But all of those costs pale into insignificance next to the gains from the syntax. Lambdas are game-changers for C++. Pre-C++11, people would avoid simple algorithms like `transform`, because writing out the equivalent code was often easier than providing a functor. That's no longer the case.

Now, I'm not saying that any of the terse syntaxes are as valuable as lambdas are. But my point is that novel syntax should not be avoided simply because it is novel; you have to look at the benefits of it.

This is the reason why I hate concept introduction syntax. It's not that it has novel syntax; it's that the novel syntax doesn't buy much. Yes, concept introduction is shorter than the full `requires` clause. But it's not shorter enough in enough cases to be worth the syntactic burden.

The nice thing about Herb's syntax is how regular it is. It works the same everywhere. It provides the same benefit everywhere. It may be novel syntax, but it solves many problems due to its regularity. It allows you to concisely fairly obvious things.

Now, you may argue that no terse syntax is worth the syntactic burden. I rather disagree: there are too many cases where the function parameters and template parameters match each other to say that making that function declaration shorter isn't worth the time and effort. Applying concepts to variables, even function parameters, makes too much sense to not be worth pursuing.

Nicol Bolas

unread,
Jun 19, 2018, 10:52:27 AM6/19/18
to ISO C++ Standard - Future Proposals
On Tuesday, June 19, 2018 at 10:41:23 AM UTC-4, Hyman Rosen wrote:
I don't like this.  I think it overlaps too much with non-type parameters.

Yes, it does overlap with them. But since type parameters are by far the most prevalent, let's give them the synatx they deserve.

Hyman Rosen

unread,
Jun 19, 2018, 11:24:59 AM6/19/18
to std-pr...@isocpp.org

Type parameters are by far the most prevalent, yet we nevertheless call them out as such:
template <typename SumType, typename Iter>
SumType accumulate(Iter begin, Iter end, SumType init);


The point of language design isn't to come up with the most compact syntax.
It's to have a syntax that makes code lucid to its readers.  So by analogy,

template <concept Sortable S>
void sort(S &s);

would be the way to go.

And as to your point on lambdas, they definitely should have had a keyword introducer,
(lambda is good!) and trailing return types should have been introduced by return, not
by ->.  Among other things, the reluctance to break old syntax is causing new features
to be expressed as gibberish.

(Notice that I said old syntax, not old programs!  Beating my dead hobby horse again,
I say that compiler writers are all too eager to break old programs by "optimizing" away
undefined behavior that used to "just work.")

Andrey Semashev

unread,
Jun 19, 2018, 11:55:16 AM6/19/18
to std-pr...@isocpp.org
On 06/19/18 17:41, Hyman Rosen wrote:
> On Tue, Jun 19, 2018 at 5:33 AM <mihailn...@gmail.com
> <mailto:mihailn...@gmail.com>> wrote:
>
> OK, right now in flight are about FOUR proposals, trying to
> "simplify" and "make more clear" concepts usage.
> This is madness. It is madness, because NONE of it make it more
> clear! None.
>
> I agree with you, but I think there's one piece of new syntax that is OK.
> To wit:
>
> For Simple cases
> template<Sortable S>
> void sort(S& s);
>
> I don't like this.  I think it overlaps too much with non-type
> parameters.

As long as the compiler is able to see what Sortable is, there is no
problem in disambiguating it. A human may not be able to deduce it at
once, but either the naming or the use of the identifier will give a
clue. For example, in your declaration S is used as a type in the
arguments list, so it is clearly not a value and Sortable cannot be an
enum or a typedef of an integral type.

>  I would prefer
>
> void sort(auto<Sortable>& s);

I don't like this as it replaces the existing syntax of template
declaration with a new one.

> 1) The angle brackets signal that templates are involved.

Yes, but not in the way they should. This is a syntax of template
specialization, not a template declaration, which always starts with the
keyword `template`. Well, except for lambdas, but they are sufficiently
alien already.

> 2) The auto signals that the compiler is deducing something.
> 3) The keyword followed by a name in angle brackets signal that
> something is being constrained; it almost has the feeling of a cast.

The contents of angle brackets so far denoted template arguments. With
your new syntax, it is something else entirely.

Nicol Bolas

unread,
Jun 19, 2018, 11:59:38 AM6/19/18
to ISO C++ Standard - Future Proposals
On Tuesday, June 19, 2018 at 11:24:59 AM UTC-4, Hyman Rosen wrote:
On Tue, Jun 19, 2018 at 10:52 AM Nicol Bolas <jmck...@gmail.com> wrote:
On Tuesday, June 19, 2018 at 10:41:23 AM UTC-4, Hyman Rosen wrote:
I don't like this.  I think it overlaps too much with non-type parameters.

Yes, it does overlap with them. But since type parameters are by far the most prevalent, let's give them the synatx they deserve.

Type parameters are by far the most prevalent, yet we nevertheless call them out as such:
template <typename SumType, typename Iter>
SumType accumulate(Iter begin, Iter end, SumType init);


The point of language design isn't to come up with the most compact syntax.
It's to have a syntax that makes code lucid to its readers.

Verbosity should not be ignored. The more verbose a feature is, the less likely that it will be used. Adding `concept` to such a declaration changes nothing about it. It doesn't disambiguate anything to the compiler (which is perfectly capable of telling the difference between a type concept and a value concept); it exists solely for the user.

I'm not saying that "lucidity" is unimportant. But you can't just say "let's make everything take twice as long to say, even if 99% of the time it would be obvious what's going on without the extra verbage".

C could have introduced a `function` keyword when declaring functions. But... why bother? It's not like the compiler needs the extra keyword there. So why have one? Similarly, it could have had a keyword when declaring variables. Again, what's the point? The compiler doesn't need it.

Oh yes, such keywords would have disambiguate C++'s Most Vexing Parse, but that was C++'s fault, not C's fault. And even then, 99% of the time, the syntax is not ambiguous.

Adding a feature that only matters in 1% of the cases, but has to be used in 100% of the cases, is just bad syntax.

  So by analogy,

template <concept Sortable S>
void sort(S &s);

would be the way to go.

And as to your point on lambdas, they definitely should have had a keyword introducer,
(lambda is good!) and trailing return types should have been introduced by return, not
by ->.  Among other things, the reluctance to break old syntax is causing new features
to be expressed as gibberish.

Things are gibberish only until they're not. A new language appears to be gibberish until you get used to its rules and proclivities.

C++ does not need to be readable by non-C++ programmers.

Andrey Semashev

unread,
Jun 19, 2018, 12:12:00 PM6/19/18
to std-pr...@isocpp.org
Also, one important feature of the `template` header is that it gives
names to the template arguments. With your proposed syntax, the name is
not given and one has to resort to decltype hacks. And the hacks don't
even help if the return type is declared like this.

Thiago Macieira

unread,
Jun 19, 2018, 12:12:38 PM6/19/18
to std-pr...@isocpp.org
On Tuesday, 19 June 2018 08:59:38 PDT Nicol Bolas wrote:
> C could have introduced a `function` keyword when declaring functions.
> But... why bother? It's not like the compiler needs the extra keyword
> there. So why have one? Similarly, it could have had a keyword when
> declaring variables. Again, what's the point? The compiler doesn't need it.

Uh... it *did* have a keyword for variables. It was "auto". Sure, it was a
legacy of B, which did not have types and only had storage keywords.

It was removed because it provided no extra information to anyone. The only
place you could use it, its meaning was already implied. That's almost like
the "extern" keyword, which in almost all cases where it can be used (in C++),
its meaning is implied. And the place where it can be used where it changes
meaning, you shouldn't use it because it leads to incompatible behaviour
between compilers.

So I'm with you that adding "concept" there is a nuisance. It would be another
"typename", where the compiler knows what you meant, but tells you to change
it anyway. So the only reason to have it would be if some compiler needs the
disambiguation.

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center



mihailn...@gmail.com

unread,
Jun 19, 2018, 12:32:37 PM6/19/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com


On Tuesday, June 19, 2018 at 5:49:49 PM UTC+3, Nicol Bolas wrote:


On Tuesday, June 19, 2018 at 5:33:54 AM UTC-4, mihailn...@gmail.com wrote:
OK, right now in flight are about FOUR proposals, trying to "simplify" and "make more clear" concepts usage.

This is madness. It is madness, because NONE of it make it more clear! None. 

By inviting new language constructs one does not make things "more clear", it only adds more things to learn.

The worst part is - we have working solution that is clear. Granted verbose, but clear. 

If one makes it Not verbose but Not clear (not self-explanatory, need learning) also one gains nothing!

Clarity is ultimately a measure of time. Variadic templates are not "clear" to people who've never seen them. UDLs are not "clear" to people who've never seen them. Lambdas are not "clear" to people who've never seen them. Structured bindings are not "clear" to people who've never seen them. And God knows rvalue references and forwarding references would utterly baffle people who've never seen them.

All of these things are clear to us now because we are used to them. That's the only reason why they are clear. Your hypothetical time traveler from the C++98/03 days would be confused by the simplest of modern C++11 code.

And that's OK.

But the problem is we have syntax that is clear to old user, even if it is new!
 

Saying that a syntax is wrong just because we're not used to it is not helpful. It's far more useful to look at things from a cost/benefit analysis.

Lambdas are probably the best example, because they don't do anything that you couldn't do yourself, either with in-situ struct declarations or out-of-function declarations. So their benefit is purely convenience.

Lambdas have a huge syntactic cost. They have novel introduction syntax, re-appropriating something that looks like an array into a function/class declaration. They are functions that can be declared without parameters, without even `()`. They deduce the return value unless you specify otherwise. They allow `auto` in parameter lists. They can capture values/expressions in a myriad of ways. And so forth.

All of this represents a syntactic variance relative to regular functions. And thus, it is a burden, a cost for entry that people have to learn.

But all of those costs pale into insignificance next to the gains from the syntax. Lambdas are game-changers for C++. Pre-C++11, people would avoid simple algorithms like `transform`, because writing out the equivalent code was often easier than providing a functor. That's no longer the case. 

Now, I'm not saying that any of the terse syntaxes are as valuable as lambdas are. But my point is that novel syntax should not be avoided simply because it is novel; you have to look at the benefits of it.

 

'requires' is the similar of lambdas; in place of the enable_if magic. It is new syntax, yet clear.


 

This is the reason why I hate concept introduction syntax. It's not that it has novel syntax; it's that the novel syntax doesn't buy much. Yes, concept introduction is shorter than the full `requires` clause. But it's not shorter enough in enough cases to be worth the syntactic burden.

I agree 100% obviously. 
 

The nice thing about Herb's syntax is how regular it is. It works the same everywhere. It provides the same benefit everywhere. It may be novel syntax, but it solves many problems due to its regularity. It allows you to concisely fairly obvious things.

Sorry, but that syntax is literally taking the hated introduction syntax and splatting it all over the entire Concepts proposal just to be "consistent"!
And it is syntax for the sake of syntax because it is not technically needed - no problem to be solved. 

And, as said it has nasty problems, from the fact it is not obvious in any way, to the metal overlap with initialization.

Number{} x;
x = Number{};

And again NO PROBLEM NEEDS SOLVING! None. 
 

Now, you may argue that no terse syntax is worth the syntactic burden. I rather disagree: there are too many cases where the function parameters and template parameters match each other to say that making that function declaration shorter isn't worth the time and effort. Applying concepts to variables, even function parameters, makes too much sense to not be worth pursuing.

Ok, however these are "nice" and nice things can wait, there is no pressing issue here!
Second, in 10+ years the results ARE WORSE. All of them! 
Third the real community is still to have its say. Any additional syntax should wait for the real feedback and the real requirements. 

To be specific they are worse because they try to do things inline instead of laying them out separately. Its like not having typdef and we are forced  to always use complex types inline
Consider the decades old example unsinged int. We have typedef for it uint. Done. 

It is exactly the same here. People will always want "one thing" as "the type" and any decorations will be a chore.

Second sin is inviting syntax not for the compiler, but the user. This is not only not needed - tools (in that case simple coloring) and conventions cover that perfectly - but creates visual load for information which might not be immediately needed. 
And type/concept information is often exactly that type of information, that's why auto is so successful. 
Code logic is often independent of type and if one wants to focus on it, the visual noise is just that - noise.
Now, if one wants to focus on the types - ctrl-click and go to definition and see if it is a class or a concept, study it in isolation. No need to flood regular core logic with million type nuances and decorations. 


Sill - was there ever before a syntax added just for humans and not the compiler?
 

Hyman Rosen

unread,
Jun 19, 2018, 12:40:09 PM6/19/18
to std-pr...@isocpp.org
On Tue, Jun 19, 2018 at 12:12 PM Thiago Macieira <thi...@macieira.org> wrote:
So I'm with you that adding "concept" there is a nuisance. It would be another
"typename", where the compiler knows what you meant, but tells you to change
it anyway. So the only reason to have it would be if some compiler needs the
disambiguation.

The reason to have it is to make the code more readable and understandable to
people. In Ada, statements are terminated to match their beginnings.  One writes

if condition then statements end if;
MyLoop: while condition loop statements end loop MyLoop;

Now, the compiler has no need for the tokens after end.  But the people reading the
code find it useful to see them, so Ada has them.

The notion that one should design languages to minimize characters typed was
ridiculous back in the day when Ada designers had C's bad examples, and it's still
ridiculous.

j c

unread,
Jun 19, 2018, 12:40:31 PM6/19/18
to std-pr...@isocpp.org
Of course it does, otherwise nobody will bother to learn it and it'll go the way of cobol and perl.
It's not like C++ lets people build enterprise-level apps easily as it is, let's not put another hurdle in front of would-be developers.

Hyman Rosen

unread,
Jun 19, 2018, 12:44:40 PM6/19/18
to std-pr...@isocpp.org
On Tue, Jun 19, 2018 at 12:32 PM <mihailn...@gmail.com> wrote:
Sill - was there ever before a syntax added just for humans and not the compiler?

There certainly was in Ada, as I just posted in another message:


MyLoop: while condition loop statements end loop MyLoop;

The extra tokens after end are there for humans. The compiler would be fine without them.

Andrey Semashev

unread,
Jun 19, 2018, 12:50:55 PM6/19/18
to std-pr...@isocpp.org
On 06/19/18 19:39, Hyman Rosen wrote:
> On Tue, Jun 19, 2018 at 12:12 PM Thiago Macieira <thi...@macieira.org
> <mailto:thi...@macieira.org>> wrote:
>
> So I'm with you that adding "concept" there is a nuisance. It would
> be another
> "typename", where the compiler knows what you meant, but tells you
> to change
> it anyway. So the only reason to have it would be if some compiler
> needs the
> disambiguation.
>
>
> The reason to have it is to make the code more readable and
> understandable to
> people. In Ada, statements are terminated to match their beginnings.
> One writes
>
> *if* /condition/ *then* /statements/ *end if;*
> MyLoop: *while* /condition/ *loop* /statements/ *end loop* MyLoop;
>
> Now, the compiler has no need for the tokens after *end*.  But the
> people reading the
> code find it useful to see them, so Ada has them.

I think, comments already fill the role for such superfluous tokens
quite nicely.

Thiago Macieira

unread,
Jun 19, 2018, 12:52:13 PM6/19/18
to std-pr...@isocpp.org
On Tuesday, 19 June 2018 09:39:55 PDT Hyman Rosen wrote:
> The notion that one should design languages to minimize characters typed was
> ridiculous back in the day when Ada designers had C's bad examples, and
> it's still ridiculous.

I don't think the issue is the to save a few characters typed, but to create a
consistent and understandable language, one that can be taught.

I remember when I didn't understand the "typename" rule, as compilers about 10
years ago weren't good at enforcing it. My rule was, "if the compiler
complains while compiling templates, add 'typename'".

But I don't think it's even that, here. The keyword usage would be consistent.

This is a subjective call, a judgement one. The argument is that the "concept"
keyword in that position does not add any value, since it was already
understood by the developer what was meant. I agree with that, since you solve
this with naming conventions: concepts are adjectives (usually ending in
-able), concrete types are nouns.

Hyman Rosen

unread,
Jun 19, 2018, 12:52:35 PM6/19/18
to std-pr...@isocpp.org
On Tue, Jun 19, 2018 at 12:50 PM Andrey Semashev <andrey....@gmail.com> wrote:
I think, comments already fill the role for such superfluous tokens quite nicely.

Only if they're required. 

Hyman Rosen

unread,
Jun 19, 2018, 1:01:54 PM6/19/18
to std-pr...@isocpp.org
On Tue, Jun 19, 2018 at 12:52 PM Thiago Macieira <thi...@macieira.org> wrote:
This is a subjective call, a judgement one. The argument is that the "concept"
keyword in that position does not add any value, since it was already
understood by the developer what was meant. I agree with that, since you solve
this with naming conventions: concepts are adjectives (usually ending in
-able), concrete types are nouns.

This is rather akin to saying that published books should be written in shorthand.
Human language is full of fillips and redundancies that guide readers toward more
easily understanding what is being communicated.  Programming languages are
used to control the operations of computers, but they are meant for humans to read
and write, and should therefore contain the literary features that will enhance that.

The "added value" is that the eye is drawn to the concept keyword, and the brain
says, "ah, that is the name of a concept".  It reduces the cognitive load on the reader.

Thiago Macieira

unread,
Jun 19, 2018, 1:17:11 PM6/19/18
to std-pr...@isocpp.org
On Tuesday, 19 June 2018 10:01:40 PDT Hyman Rosen wrote:
> The "added value" is that the eye is drawn to the concept keyword, and the
> brain
> says, "ah, that is the name of a concept". It reduces the cognitive load
> on the reader.

I understand what you're saying. I just don't agree it's necessary.

Jeffrey Yasskin

unread,
Jun 19, 2018, 1:36:25 PM6/19/18
to std-pr...@isocpp.org
Please don't call folks' proposals "madness". It both minimizes the difficulties of folks with actual mental illnesses, and is unnecessarily offensive to folks who have honest differences of opinion.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/19c57a60-e883-4474-b106-7ff2ebc122ee%40isocpp.org.

Nicol Bolas

unread,
Jun 19, 2018, 1:38:01 PM6/19/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com


On Tuesday, June 19, 2018 at 12:32:37 PM UTC-4, mihailn...@gmail.com wrote:


On Tuesday, June 19, 2018 at 5:49:49 PM UTC+3, Nicol Bolas wrote:


On Tuesday, June 19, 2018 at 5:33:54 AM UTC-4, mihailn...@gmail.com wrote:
OK, right now in flight are about FOUR proposals, trying to "simplify" and "make more clear" concepts usage.

This is madness. It is madness, because NONE of it make it more clear! None. 

By inviting new language constructs one does not make things "more clear", it only adds more things to learn.

The worst part is - we have working solution that is clear. Granted verbose, but clear. 

If one makes it Not verbose but Not clear (not self-explanatory, need learning) also one gains nothing!

Clarity is ultimately a measure of time. Variadic templates are not "clear" to people who've never seen them. UDLs are not "clear" to people who've never seen them. Lambdas are not "clear" to people who've never seen them. Structured bindings are not "clear" to people who've never seen them. And God knows rvalue references and forwarding references would utterly baffle people who've never seen them.

All of these things are clear to us now because we are used to them. That's the only reason why they are clear. Your hypothetical time traveler from the C++98/03 days would be confused by the simplest of modern C++11 code.

And that's OK.

But the problem is we have syntax that is clear to old user, even if it is new!

So what? That doesn't make syntax that isn't clear to old users a priori bad. Syntax should be judged on its own merits, not on the merits of some hypothetical user who hasn't kept up with the language in a decade.

Saying that a syntax is wrong just because we're not used to it is not helpful. It's far more useful to look at things from a cost/benefit analysis.

Lambdas are probably the best example, because they don't do anything that you couldn't do yourself, either with in-situ struct declarations or out-of-function declarations. So their benefit is purely convenience.

Lambdas have a huge syntactic cost. They have novel introduction syntax, re-appropriating something that looks like an array into a function/class declaration. They are functions that can be declared without parameters, without even `()`. They deduce the return value unless you specify otherwise. They allow `auto` in parameter lists. They can capture values/expressions in a myriad of ways. And so forth.

All of this represents a syntactic variance relative to regular functions. And thus, it is a burden, a cost for entry that people have to learn.

But all of those costs pale into insignificance next to the gains from the syntax. Lambdas are game-changers for C++. Pre-C++11, people would avoid simple algorithms like `transform`, because writing out the equivalent code was often easier than providing a functor. That's no longer the case. 

Now, I'm not saying that any of the terse syntaxes are as valuable as lambdas are. But my point is that novel syntax should not be avoided simply because it is novel; you have to look at the benefits of it.

'requires' is the similar of lambdas; in place of the enable_if magic. It is new syntax, yet clear.


 

This is the reason why I hate concept introduction syntax. It's not that it has novel syntax; it's that the novel syntax doesn't buy much. Yes, concept introduction is shorter than the full `requires` clause. But it's not shorter enough in enough cases to be worth the syntactic burden.

I agree 100% obviously. 
 

The nice thing about Herb's syntax is how regular it is. It works the same everywhere. It provides the same benefit everywhere. It may be novel syntax, but it solves many problems due to its regularity. It allows you to concisely fairly obvious things.

Sorry, but that syntax is literally taking the hated introduction syntax and splatting it all over the entire Concepts proposal just to be "consistent"!

This is why your "I agree 100% obviously" is incorrect. You agree with my conclusion, not my reasoning.

I dislike the concept introduction syntax for the reasons I specified: it does not carry its own weight. The syntax does not provide nearly enough benefits compared to its cost.

By "splatting it all over the entire Concepts proposal", the syntax gains additional benefits. For example:

void forward_func(Concept{Typename} &&t)
{
  func
(std::forward<Typename>(t));
}

See? No `decltype(t)` gymnastics.

Similarly, I can do this:

void func(Iterator{It} first, It last)
{
}

And that spells out exactly what it means. Sure, I could have used `template<Iterator It>`, but this is shorter without losing meaning. Yes, you have to learn what that means, but in a lambda, this is worthwhile:

[](Iterator{It} first, It last) {...}

vs
.

[]<Iterator It>(It first, It last) {...}

Now these aren't huge differences. They're not universe-changing, world-shaking benefits. But they're significant, and to me, they allow this syntax to carry its own weight. Learning this syntax pays for itself in making concepts more usable.

And it is syntax for the sake of syntax because it is not technically needed - no problem to be solved. 

So are lambdas. As I pointed out, there is no technical reason why you cannot replace every lambda ever with a user-written type.

And, as said it has nasty problems, from the fact it is not obvious in any way, to the metal overlap with initialization.

Number{} x;
x = Number{};

And again NO PROBLEM NEEDS SOLVING! None. 
 

Now, you may argue that no terse syntax is worth the syntactic burden. I rather disagree: there are too many cases where the function parameters and template parameters match each other to say that making that function declaration shorter isn't worth the time and effort. Applying concepts to variables, even function parameters, makes too much sense to not be worth pursuing.

Ok, however these are "nice" and nice things can wait, there is no pressing issue here!

Concepts are "nice things" too. But I think we can all agree we've waited too long for them.
 
Second, in 10+ years the results ARE WORSE. All of them!

... huh?
 
Third the real community is still to have its say. Any additional syntax should wait for the real feedback and the real requirements.

Every argument you make after this point against terse templates is an argument you could make against lambdas. But we still have them. Why?

Because the benefits outweigh the costs.

The syntactic costs of terse template syntax is relatively minimal, whichever syntax it may be.The benefits are still significant enough for those costs to be meaningful.
 
Sill - was there ever before a syntax added just for humans and not the compiler?

In C++? No; if compilers can figure it out, C and C++ tend to be of the belief that people can too.

mihailn...@gmail.com

unread,
Jun 19, 2018, 2:48:17 PM6/19/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com
Are they significant enough to add de facto brand new syntax
A syntax which could be used for something else in a decade? 
A syntax that does not introduce new features, but only adds second, even third way of doing the same thing?



And it is syntax for the sake of syntax because it is not technically needed - no problem to be solved. 

So are lambdas. As I pointed out, there is no technical reason why you cannot replace every lambda ever with a user-written type.

And, as said it has nasty problems, from the fact it is not obvious in any way, to the metal overlap with initialization.

Number{} x;
x = Number{};

And again NO PROBLEM NEEDS SOLVING! None. 
 

Now, you may argue that no terse syntax is worth the syntactic burden. I rather disagree: there are too many cases where the function parameters and template parameters match each other to say that making that function declaration shorter isn't worth the time and effort. Applying concepts to variables, even function parameters, makes too much sense to not be worth pursuing.

Ok, however these are "nice" and nice things can wait, there is no pressing issue here!

Concepts are "nice things" too. But I think we can all agree we've waited too long for them.
 
Second, in 10+ years the results ARE WORSE. All of them!

... huh?
 
Third the real community is still to have its say. Any additional syntax should wait for the real feedback and the real requirements.

Every argument you make after this point against terse templates is an argument you could make against lambdas. But we still have them. Why?

Because the benefits outweigh the costs.


Your comparison to lambdas would have been correct only if we had a concurrent terse lambda proposal being developed at the same time as the regular one. 
Even worse - to have the terse lambda blocking normal lambda. 

Because we are there with Concepts. 

We have two good (as in clear, powerful, understandable, carrying the legacy forward, (C++) user friendly) ways to use Concepts and we insist of third way. Almost no matter the cost. 
And the results are not good. Not measurably good, given the cost.

As I said I am not against terse, my point is to just play it safe (for now):

 - No syntax-for-humans-only.
 - No new syntactical concepts, which are simply an alternative

That's it.

In 5 years - revisit. Just like we revisited lambdas multiple times in multiple forms.

Nicol Bolas

unread,
Jun 19, 2018, 3:15:35 PM6/19/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com
That's a judgement call, but I would say "yes".

A syntax which could be used for something else in a decade?

OK, so let's review the two syntaxes in question (because the committee has essentially boiled them down to just two).

There's Herb's proposal, which is `ConceptName{stuff}`. And there's the Concepts TS terse syntax but with `template` applied to functions that use them (except for lambdas which get it without `template`).

What could you use `ConceptName{stuff}` for in the future? Do you have any ideas at all where such syntax might be useful?

Similarly, what would `template <function definition>` mean in some hypothetical future?

I understand and appreciate the idea of not burning precious syntax for trivial things. But we're not talking about prime syntactic real estate here.

A syntax that does not introduce new features, but only adds second, even third way of doing the same thing?

It doesn't matter how many ways there are of doing something. What matters is whether those ways are clear and convenient to use. Template headers are clear but inconvenient.


And it is syntax for the sake of syntax because it is not technically needed - no problem to be solved. 

So are lambdas. As I pointed out, there is no technical reason why you cannot replace every lambda ever with a user-written type.

And, as said it has nasty problems, from the fact it is not obvious in any way, to the metal overlap with initialization.

Number{} x;
x = Number{};

And again NO PROBLEM NEEDS SOLVING! None. 
 

Now, you may argue that no terse syntax is worth the syntactic burden. I rather disagree: there are too many cases where the function parameters and template parameters match each other to say that making that function declaration shorter isn't worth the time and effort. Applying concepts to variables, even function parameters, makes too much sense to not be worth pursuing.

Ok, however these are "nice" and nice things can wait, there is no pressing issue here!

Concepts are "nice things" too. But I think we can all agree we've waited too long for them.
 
Second, in 10+ years the results ARE WORSE. All of them!

... huh?
 
Third the real community is still to have its say. Any additional syntax should wait for the real feedback and the real requirements.

Every argument you make after this point against terse templates is an argument you could make against lambdas. But we still have them. Why?

Because the benefits outweigh the costs.

Your comparison to lambdas would have been correct only if we had a concurrent terse lambda proposal being developed at the same time as the regular one. 

But they did. Go look at some of the old lambda proposals. There were ideas about dropping the parameter typename identifiers and so forth even back then. They didn't pan out, but there was discussion about them concurrently with the broader lambda syntax. And such things would have been optional rather than mandatory.

Even worse - to have the terse lambda blocking normal lambda. Because we are there with Concepts.

Since when has terse templates blocked concepts? The Concepts TS wasn't ready for C++17; questions about terse syntax were just one of the reasons why. And Concepts-sans-terse syntax was voted into C++20 last year. So we aren't "there" at all.

Not unless one of the 5 national bodies is threatening not to vote for C++20 without some form of terse templates.

mihailn...@gmail.com

unread,
Jun 19, 2018, 4:57:07 PM6/19/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com
Something{stuff} was already considered for structured bindings. 

I don't know what the future holds, but we are clearly chipping away syntax ground just for an alternative.
 

Similarly, what would `template <function definition>` mean in some hypothetical future?

I understand and appreciate the idea of not burning precious syntax for trivial things. But we're not talking about prime syntactic real estate here.

A syntax that does not introduce new features, but only adds second, even third way of doing the same thing?

It doesn't matter how many ways there are of doing something. What matters is whether those ways are clear and convenient to use. Template headers are clear but inconvenient.


And it is syntax for the sake of syntax because it is not technically needed - no problem to be solved. 

So are lambdas. As I pointed out, there is no technical reason why you cannot replace every lambda ever with a user-written type.

And, as said it has nasty problems, from the fact it is not obvious in any way, to the metal overlap with initialization.

Number{} x;
x = Number{};

And again NO PROBLEM NEEDS SOLVING! None. 
 

Now, you may argue that no terse syntax is worth the syntactic burden. I rather disagree: there are too many cases where the function parameters and template parameters match each other to say that making that function declaration shorter isn't worth the time and effort. Applying concepts to variables, even function parameters, makes too much sense to not be worth pursuing.

Ok, however these are "nice" and nice things can wait, there is no pressing issue here!

Concepts are "nice things" too. But I think we can all agree we've waited too long for them.
 
Second, in 10+ years the results ARE WORSE. All of them!

... huh?
 
Third the real community is still to have its say. Any additional syntax should wait for the real feedback and the real requirements.

Every argument you make after this point against terse templates is an argument you could make against lambdas. But we still have them. Why?

Because the benefits outweigh the costs.

Your comparison to lambdas would have been correct only if we had a concurrent terse lambda proposal being developed at the same time as the regular one. 

But they did. Go look at some of the old lambda proposals. There were ideas about dropping the parameter typename identifiers and so forth even back then. They didn't pan out, but there was discussion about them concurrently with the broader lambda syntax. And such things would have been optional rather than mandatory.

Even worse - to have the terse lambda blocking normal lambda. Because we are there with Concepts.

Since when has terse templates blocked concepts? The Concepts TS wasn't ready for C++17; questions about terse syntax were just one of the reasons why. And Concepts-sans-terse syntax was voted into C++20 last year. So we aren't "there" at all.

Not unless one of the 5 national bodies is threatening not to vote for C++20 without some form of terse templates.

Funny how we both have commented under that report (not that I remember!). 

In any case Concepts-sans-terse is not frozen. And that is what worries me. 
On the plus side, it seems the name introducers are not in as well so there is still hope.

Gašper Ažman

unread,
Jun 19, 2018, 6:06:21 PM6/19/18
to std-pr...@isocpp.org, Михаил Найденов
The Concept{} syntax could be used for archetypes.

G

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.

Nicol Bolas

unread,
Jun 19, 2018, 6:32:55 PM6/19/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com
On Tuesday, June 19, 2018 at 4:57:07 PM UTC-4, mihailn...@gmail.com wrote:
On Tuesday, June 19, 2018 at 10:15:35 PM UTC+3, Nicol Bolas wrote:
On Tuesday, June 19, 2018 at 2:48:17 PM UTC-4, mihailn...@gmail.com wrote:
Are they significant enough to add de facto brand new syntax?

That's a judgement call, but I would say "yes".

A syntax which could be used for something else in a decade?

OK, so let's review the two syntaxes in question (because the committee has essentially boiled them down to just two).

There's Herb's proposal, which is `ConceptName{stuff}`. And there's the Concepts TS terse syntax but with `template` applied to functions that use them (except for lambdas which get it without `template`).

What could you use `ConceptName{stuff}` for in the future? Do you have any ideas at all where such syntax might be useful?


Something{stuff} was already considered for structured bindings.

I don't know what the future holds, but we are clearly chipping away syntax ground just for an alternative.

So your hypothetical is a syntax that was considered and rejected on grounds having nothing to do with concepts. So if concepts had used it, it would still have been rejected, just with one more reason to do so.

I'm having a problem seeing the potential in this syntax.

Again, I recognize the importance of not spending syntax just because it's there. Generally. But we're not talking about "generally"; we're talking about a specific piece of syntax. If there is some potential competition for this syntax that could be more useful, that'd be one thing. But if there is no such competition, and we can solve a bunch of (relatively minor) problems using this syntax, then I say take it.

Unused syntax helps nobody.

In any case Concepts-sans-terse is not frozen. And that is what worries me.

Are you also worried that contracts aren't frozen either? Or that ranges isn't frozen? Or `operator<=>` isn't frozen yet?

They're not frozen because C++20 is not frozen. That's how standards are developed. Concepts is decoupled from terse syntax; one is in, and the other is out.

There is no way the committee could give you more than they've already given you. Take the win and move on.

mihailn...@gmail.com

unread,
Jun 20, 2018, 2:46:56 AM6/20/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com


On Wednesday, June 20, 2018 at 1:32:55 AM UTC+3, Nicol Bolas wrote:
On Tuesday, June 19, 2018 at 4:57:07 PM UTC-4, mihailn...@gmail.com wrote:
On Tuesday, June 19, 2018 at 10:15:35 PM UTC+3, Nicol Bolas wrote:
On Tuesday, June 19, 2018 at 2:48:17 PM UTC-4, mihailn...@gmail.com wrote:
Are they significant enough to add de facto brand new syntax?

That's a judgement call, but I would say "yes".

A syntax which could be used for something else in a decade?

OK, so let's review the two syntaxes in question (because the committee has essentially boiled them down to just two).

There's Herb's proposal, which is `ConceptName{stuff}`. And there's the Concepts TS terse syntax but with `template` applied to functions that use them (except for lambdas which get it without `template`).

What could you use `ConceptName{stuff}` for in the future? Do you have any ideas at all where such syntax might be useful?


Something{stuff} was already considered for structured bindings.

I don't know what the future holds, but we are clearly chipping away syntax ground just for an alternative.

So your hypothetical is a syntax that was considered and rejected on grounds having nothing to do with concepts. So if concepts had used it, it would still have been rejected, just with one more reason to do so.

I'm having a problem seeing the potential in this syntax.

Again, I recognize the importance of not spending syntax just because it's there. Generally. But we're not talking about "generally"; we're talking about a specific piece of syntax. If there is some potential competition for this syntax that could be more useful, that'd be one thing. But if there is no such competition, and we can solve a bunch of (relatively minor) problems using this syntax, then I say take it.
 

You see problems solved, but I see none. That's where we differ. 

But lets say we solved a minor problem. And we pay the price of new syntax. Looks like 1:1 for now. 

However, the downsides with in-place are greater then this tradeoff alone. 

The biggest downside is that it opens the door for a dialect of template code - it is so all encompassing that it start to create alternative templates language. 

How long until someone request this 

func(class{Container}& c);


And what will be the one to teach?

template<Concept {C}> 
void f(C);
or
void f(Concept{C});

Which one? Is the first one legacy now? 


And how can we explain we have three syntaxes to a student and only one of them is not a natural evolution? 
Because we don't have this problem with the standard notations - they are ALL evolutionarily!


Lets talk about local scope

Do we really need or want this, or was that "a nice side effect"

Number{N2} sum = x+y;

Do we really want two (completely different) declarations in one line?!? (Putting aside the fact in local scope the syntax looks like construction and/or inline class definition)

Honestly, the issues with in-place are far and beyond "we paid a bit of syntax and got some minor problems solved".  

 

Unused syntax helps nobody.

In any case Concepts-sans-terse is not frozen. And that is what worries me.

Are you also worried that contracts aren't frozen either? Or that ranges isn't frozen? Or `operator<=>` isn't frozen yet?

They're not frozen because C++20 is not frozen. That's how standards are developed. Concepts is decoupled from terse syntax; one is in, and the other is out.

I *wish* that was the case, but "the other" is not 'out' - it is still actively pursued. Hence this topic.

My wish is to have this discussion after C++ 23 instead.  

Nicol Bolas

unread,
Jun 20, 2018, 12:44:58 PM6/20/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com
Your earlier statement suggested that you were concerned that terse syntax was interferring with the rest of concepts being shipped: "Even worse - to have the terse lambda blocking normal lambda. Because we are there with Concepts."

But now, you're saying that you're not concerned with when the rest of concepts is shipped. You're merely concerned that terse syntax exists at all. That people are working on trying to get a feature into the standard that you don't want.

Let me put it a different way. Do you really want to have to write this to have a conceptualized lambda:

[]<Concept C1, Concept C2>(C1 &c1, const C2 &c2) {...}

Rather than

[](Concept &c1, const Concept &c2) {...}

Or

[](Concept{} &c1, const Concept{} &c2) {...}

Why is the first one better than the second or third? What is all of that verbiage providing?

Hyman Rosen

unread,
Jun 20, 2018, 1:37:45 PM6/20/18
to std-pr...@isocpp.org, Михаил Найденов
On Wed, Jun 20, 2018 at 12:45 PM Nicol Bolas <jmck...@gmail.com> wrote:
Let me put it a different way. Do you really want to have to write this to have a conceptualized lambda:

[]<Concept C1, Concept C2>(C1 &c1, const C2 &c2) {...}
Rather than
[](Concept &c1, const Concept &c2) {...}
Or
[](Concept{} &c1, const Concept{} &c2) {...}

Why is the first one better than the second or third? What is all of that verbiage providing?

I still want

[](auto<Concept>& c1, const auto<Concept>& c2) { ... }

One thing the extra verbiage here provides is a hint that deduction is happening
independently for each parameter.  It's not intuitive that in

[](Concept& c1, const Concept& c2) { ... }

the two parameter types can be unrelated, except that they both satisfy Concept.
(At least I assume that's the case?)

Andrey Semashev

unread,
Jun 20, 2018, 2:26:25 PM6/20/18
to std-pr...@isocpp.org
On 06/20/18 19:44, Nicol Bolas wrote:
>
> Let me put it a different way. Do you /really/ want to have to write
> this to have a conceptualized lambda:
>
> |
> []<ConceptC1,ConceptC2>(C1 &c1,constC2 &c2){...}
>
> Ratherthan
>
> [](Concept&c1,constConcept&c2){...}
>
> Or
>
> [](Concept{}&c1,constConcept{}&c2){...}
> |

I, actually, would prefer the first syntax.

> Why is the first one better than the second or third? What is all of
> that verbiage providing?

It provides somewhat consistent syntax, which is already a significant
enough advantage for me. It also provides names for the argument types,
which may be useful.

mihailn...@gmail.com

unread,
Jun 20, 2018, 2:54:47 PM6/20/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com


On Wednesday, June 20, 2018 at 7:44:58 PM UTC+3, Nicol Bolas wrote:
On Wednesday, June 20, 2018 at 2:46:56 AM UTC-4, mihailn...@gmail.com wrote:
On Wednesday, June 20, 2018 at 1:32:55 AM UTC+3, Nicol Bolas wrote:
On Tuesday, June 19, 2018 at 4:57:07 PM UTC-4, mihailn...@gmail.com wrote:
On Tuesday, June 19, 2018 at 10:15:35 PM UTC+3, Nicol Bolas wrote:
On Tuesday, June 19, 2018 at 2:48:17 PM UTC-4, mihailn...@gmail.com wrote:
In any case Concepts-sans-terse is not frozen. And that is what worries me.

Are you also worried that contracts aren't frozen either? Or that ranges isn't frozen? Or `operator<=>` isn't frozen yet?

They're not frozen because C++20 is not frozen. That's how standards are developed. Concepts is decoupled from terse syntax; one is in, and the other is out.

I *wish* that was the case, but "the other" is not 'out' - it is still actively pursued. Hence this topic.

My wish is to have this discussion after C++ 23 instead.

Your earlier statement suggested that you were concerned that terse syntax was interferring with the rest of concepts being shipped: "Even worse - to have the terse lambda blocking normal lambda. Because we are there with Concepts."

But now, you're saying that you're not concerned with when the rest of concepts is shipped. You're merely concerned that terse syntax exists at all. That people are working on trying to get a feature into the standard that you don't want. 

I am not concerned when the rest will ship if ever, I even think it is better to postpone (so Concepts are not slowed... or worse) and get some real feedback. 

But, yes I am VERY, VERY concerned about in-place making it into the language. As I said - this is (the base of) a dialect on templates in general. 
I also question 2-in-1 declarations that come with it.
 

Let me put it a different way. Do you really want to have to write this to have a conceptualized lambda:

[]<Concept C1, Concept C2>(C1 &c1, const C2 &c2) {...}

Rather than

[](Concept &c1, const Concept &c2) {...}

Or

[](Concept{} &c1, const Concept{} &c2) {...}

Why is the first one better than the second or third? What is all of that verbiage providing?

I personally have no problem with either 1 or 2. 

And BTW the last example should be [](Concept{C1} &c1, const Concept{C2} &c2) {…} to match the first, otherwise the {} will surely be optional (as the proposal anticipates)

This is new language - new syntax and new idioms - 2-in-1 instructions. (again, putting aside the mental overlap with object creation)

All this right after we doubled down on the 30 years old name introducing syntax - <Type Name> - with lambdas as well! 


And I ask again - what is the problem of having comma separated template arguments <Concept C1, C2> ?

And if we want the required statement to be able to also introduce, why does it need brand new syntax? 

instead of 
Mergeable{In1, In2, Out} 
Out merge(In1,In1,In2,In2,Out);

just 
requires Mergeable<In1, In2, Out> 
Out merge(In1,In1,In2,In2,Out);

No new syntax AND it is clear we are starting a template.
Is there a parsing problem with that? Was something like that considered? 

Gašper Ažman

unread,
Jun 20, 2018, 3:42:29 PM6/20/18
to std-pr...@isocpp.org, Михаил Найденов
I have an issue with reserving Concept{} because that means "create an archetype of Concept, substituting no archetype free variables" to me.

Archetypes will be important at some point, or at least I hope so - they are really important for completion and body-checking, and when you have that, why not be able to use them in unevaluated contexts?

G

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.

To post to this group, send email to std-pr...@isocpp.org.

Nicol Bolas

unread,
Jun 20, 2018, 3:51:15 PM6/20/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com
On Wednesday, June 20, 2018 at 3:42:29 PM UTC-4, Gašper Ažman wrote:
I have an issue with reserving Concept{} because that means "create an archetype of Concept, substituting no archetype free variables" to me.

OK, but what is an "archetype of Concept", and why would most C++ programmers think that this syntax means that?

Archetypes will be important at some point, or at least I hope so - they are really important for completion and body-checking, and when you have that, why not be able to use them in unevaluated contexts?

Because certain members of the committee have made it abundantly clear that "Concepts" in C++ will never go beyond their current constraints. There will be no "completion and body-checking" in C++. Ever.

Gašper Ažman

unread,
Jun 20, 2018, 4:04:44 PM6/20/18
to std-pr...@isocpp.org, Михаил Найденов
On Wed, Jun 20, 2018 at 8:51 PM, Nicol Bolas <jmck...@gmail.com> wrote:
On Wednesday, June 20, 2018 at 3:42:29 PM UTC-4, Gašper Ažman wrote:
I have an issue with reserving Concept{} because that means "create an archetype of Concept, substituting no archetype free variables" to me.

OK, but what is an "archetype of Concept", and why would most C++ programmers think that this syntax means that?

An archetype of a concept is a fictional concrete type that satisfies the syntactic constraints. Under certain conditions it can be generated from the concept specification, thus enabling completion. Body checking might be warning only, but that doesn't mean it isn't useful.
 

Archetypes will be important at some point, or at least I hope so - they are really important for completion and body-checking, and when you have that, why not be able to use them in unevaluated contexts?

Because certain members of the committee have made it abundantly clear that "Concepts" in C++ will never go beyond their current constraints. There will be no "completion and body-checking" in C++. Ever.

People's opinions change, especially in the face of evidence. Even if the past proposals weren't acceptable, why does that prohibit it in the future? If we can make it work in a way that's "right" for C++, why kill it now, before we've had the chance to do that?

The reason that syntax means Archetype to me is because Type{} is an instantiation, which means Concept{} is an instantiation - and an instantiation of a concept is a type-ish thing.

Nicol Bolas

unread,
Jun 20, 2018, 4:05:06 PM6/20/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com
On Wednesday, June 20, 2018 at 2:54:47 PM UTC-4, mihailn...@gmail.com wrote:
On Wednesday, June 20, 2018 at 7:44:58 PM UTC+3, Nicol Bolas wrote:
On Wednesday, June 20, 2018 at 2:46:56 AM UTC-4, mihailn...@gmail.com wrote:
I *wish* that was the case, but "the other" is not 'out' - it is still actively pursued. Hence this topic.

My wish is to have this discussion after C++ 23 instead.

Your earlier statement suggested that you were concerned that terse syntax was interferring with the rest of concepts being shipped: "Even worse - to have the terse lambda blocking normal lambda. Because we are there with Concepts."

But now, you're saying that you're not concerned with when the rest of concepts is shipped. You're merely concerned that terse syntax exists at all. That people are working on trying to get a feature into the standard that you don't want. 

I am not concerned when the rest will ship if ever,

When I said "rest", I meant the "non-terse template" part.

I even think it is better to postpone (so Concepts are not slowed... or worse) and get some real feedback.

But we have "real feedback". It's not like terse syntax manifested ex-nihilo sometime in 2017. It's out there in the Concepts TS, which is being used by real people.

Let me put it a different way. Do you really want to have to write this to have a conceptualized lambda:

[]<Concept C1, Concept C2>(C1 &c1, const C2 &c2) {...}

Rather than

[](Concept &c1, const Concept &c2) {...}

Or

[](Concept{} &c1, const Concept{} &c2) {...}

Why is the first one better than the second or third? What is all of that verbiage providing?

I personally have no problem with either 1 or 2.

Then why does the title of this thread call Bjarne's proposal "madness"? If you wanted to rail against Herb's proposal, then you should have focused on that specifically.

And BTW the last example should be [](Concept{C1} &c1, const Concept{C2} &c2) {…} to match the first, otherwise the {} will surely be optional (as the proposal anticipates)

Anticipation isn't the same thing as "gonna happen". Because once you make those curly braces optional, you lose the ability to easily tell whether a function is a template or not. Which was the primary problem being resolved.

This is new language - new syntax and new idioms - 2-in-1 instructions. (again, putting aside the mental overlap with object creation)

All this right after we doubled down on the 30 years old name introducing syntax - <Type Name> - with lambdas as well! 


And I ask again - what is the problem of having comma separated template arguments <Concept C1, C2> ?

Because it doesn't make things shorter. Not by nearly as much. We're talking about creating syntax that lets you see what's going on without so much text. Dropping a single word like that isn't helping.
 
And if we want the required statement to be able to also introduce, why does it need brand new syntax? 

Wait: I thought the reason you hated Herb's syntax was because it is a novel syntax. How is using `requires` to preemptively create a template any less novel?

instead of 
Mergeable{In1, In2, Out} 
Out merge(In1,In1,In2,In2,Out);

just 
requires Mergeable<In1, In2, Out> 
Out merge(In1,In1,In2,In2,Out);

No new syntax AND it is clear we are starting a template.

But nobody's suggesting that. Well OK, Bjarne is probably still hoping concept introduction syntax will make it in, but Herb's proposal doesn't do that. It does this:

Mergeable{Out, In1, In2} merge(In1, In1, In2, In2, Out);

That is, you define `Mergeable` such that it is the output type. So it's not some special syntax that begins a template function declaration. It behaves no differently than any other use of a concept for a function's output parameter, while simultaneously naming some of its template parameters for use as function parameter types.

Nicol Bolas

unread,
Jun 20, 2018, 4:44:21 PM6/20/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com
On Wednesday, June 20, 2018 at 4:04:44 PM UTC-4, Gašper Ažman wrote:
On Wed, Jun 20, 2018 at 8:51 PM, Nicol Bolas <jmck...@gmail.com> wrote:
On Wednesday, June 20, 2018 at 3:42:29 PM UTC-4, Gašper Ažman wrote:
I have an issue with reserving Concept{} because that means "create an archetype of Concept, substituting no archetype free variables" to me.

OK, but what is an "archetype of Concept", and why would most C++ programmers think that this syntax means that?

An archetype of a concept is a fictional concrete type that satisfies the syntactic constraints. Under certain conditions it can be generated from the concept specification, thus enabling completion.

If it's a "fictional" type, why do I want to name it? And if it's a type that gets generated, then I probably want to have something that looks like a regular type declaration `class Name : Concept`.

Otherwise we're in concept map territory. And nobody wants to be there.

Body checking might be warning only, but that doesn't mean it isn't useful.
 

Archetypes will be important at some point, or at least I hope so - they are really important for completion and body-checking, and when you have that, why not be able to use them in unevaluated contexts?

Because certain members of the committee have made it abundantly clear that "Concepts" in C++ will never go beyond their current constraints. There will be no "completion and body-checking" in C++. Ever.

People's opinions change, especially in the face of evidence. Even if the past proposals weren't acceptable, why does that prohibit it in the future? If we can make it work in a way that's "right" for C++, why kill it now, before we've had the chance to do that?

The moment concepts land in the standard, definition checking will be dead. Why? Because right now, a `concept` is just a constexpr expression based on template parameters. It doesn't have to use a `requires` clause; it's just a boolean value.

One of the big problems with getting definition checking is dealing with the fact that a concept is not merely a set of expressions that have to be followed (which a compiler can match expressions against), but just whatever constexpr stuff you stick in the variable. You can call arbitrary constexpr functions that do arbitrary things, and that's OK.

If your concepts are all defined that way, you can't have definition checking. At least, not without saying that you have to define your concepts using a specific syntax in order to get definition checking. In which case, you create a dichotomy between "real concepts" and "fake concepts". And if some library uses a bunch of "fake concepts", how can you have definition checking? Can you call their code that's not using real concepts with your types that follow the same "conceptual" concepts that are implemented in a non-"fake" way?

No, it just turns into a big bunch of mess. We lost the fight for definition checking the minute concepts was allowed into the standard without proven definition checking abilities. Best to let it go and move on.

The reason that syntax means Archetype to me is because Type{} is an instantiation,

It's not. A concept is a template; an instantiation of a template uses `<>`.

mihailn...@gmail.com

unread,
Jun 20, 2018, 5:51:55 PM6/20/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com


On Wednesday, June 20, 2018 at 11:05:06 PM UTC+3, Nicol Bolas wrote:
On Wednesday, June 20, 2018 at 2:54:47 PM UTC-4, mihailn...@gmail.com wrote:
On Wednesday, June 20, 2018 at 7:44:58 PM UTC+3, Nicol Bolas wrote:
On Wednesday, June 20, 2018 at 2:46:56 AM UTC-4, mihailn...@gmail.com wrote:
I *wish* that was the case, but "the other" is not 'out' - it is still actively pursued. Hence this topic.

My wish is to have this discussion after C++ 23 instead.

Your earlier statement suggested that you were concerned that terse syntax was interferring with the rest of concepts being shipped: "Even worse - to have the terse lambda blocking normal lambda. Because we are there with Concepts."

But now, you're saying that you're not concerned with when the rest of concepts is shipped. You're merely concerned that terse syntax exists at all. That people are working on trying to get a feature into the standard that you don't want. 

I am not concerned when the rest will ship if ever,

When I said "rest", I meant the "non-terse template" part.

I even think it is better to postpone (so Concepts are not slowed... or worse) and get some real feedback.

But we have "real feedback". It's not like terse syntax manifested ex-nihilo sometime in 2017. It's out there in the Concepts TS, which is being used by real people.


Well, that's debatable, considering even the STL does not use these yet. Why should anyone use them in production en masse when they are not ready? The real use begins with 20.
 

 

Let me put it a different way. Do you really want to have to write this to have a conceptualized lambda:

[]<Concept C1, Concept C2>(C1 &c1, const C2 &c2) {...}

Rather than

[](Concept &c1, const Concept &c2) {...}

Or

[](Concept{} &c1, const Concept{} &c2) {...}

Why is the first one better than the second or third? What is all of that verbiage providing?

I personally have no problem with either 1 or 2.

Then why does the title of this thread call Bjarne's proposal "madness"? If you wanted to rail against Herb's proposal, then you should have focused on that specifically.


First and foremost I apologies for overly emotional use of words. 
Second the topic is not about any specific proposal. How the title implies Bjarne's? It does not.
Third I have massive respect to both of them and in particular Herb, as he is one of the best speakers and his Zero-overhead exceptions is the single most exiting new proposal for me personally.
In general I am pro Bjarne terse, except for introducers.

What I call madness (and again, I regret) is the fact we have 100% working solution (yes, not 99%, but 100%) that the vast majority will feel at home with, that is still being "improved" and no improvement is undeniably better.
 


And BTW the last example should be [](Concept{C1} &c1, const Concept{C2} &c2) {…} to match the first, otherwise the {} will surely be optional (as the proposal anticipates)

Anticipation isn't the same thing as "gonna happen". Because once you make those curly braces optional, you lose the ability to easily tell whether a function is a template or not. Which was the primary problem being resolved.

Only goes to show one of the problems with the proposal - even the author thinks "it might" not be needed (and it is not). 
 

This is new language - new syntax and new idioms - 2-in-1 instructions. (again, putting aside the mental overlap with object creation)

All this right after we doubled down on the 30 years old name introducing syntax - <Type Name> - with lambdas as well! 


And I ask again - what is the problem of having comma separated template arguments <Concept C1, C2> ?

Because it doesn't make things shorter. Not by nearly as much. We're talking about creating syntax that lets you see what's going on without so much text. Dropping a single word like that isn't helping. 
 
And if we want the required statement to be able to also introduce, why does it need brand new syntax? 

Wait: I thought the reason you hated Herb's syntax was because it is a novel syntax. How is using `requires` to preemptively create a template any less novel?


It is not novel because it just omits something that the compiler can deduce. 
It does not introduce any new syntax and even the time traveler will understand it after he has first seen the full syntax just one time.

template<typename In1, typename In2, typename Out> //< deduce me

requires Mergeable<In1, In2, Out>
Out merge(In1,In1,In2,In2,Out);

 
In any case I am not proposing anything, just asking!



instead of 
Mergeable{In1, In2, Out} 
Out merge(In1,In1,In2,In2,Out);

just 
requires Mergeable<In1, In2, Out> 
Out merge(In1,In1,In2,In2,Out);

No new syntax AND it is clear we are starting a template.

But nobody's suggesting that. Well OK, Bjarne is probably still hoping concept introduction syntax will make it in, but Herb's proposal doesn't do that. It does this:
 
Currently it is suggested as

template<Mergeable{In1, In2, Out}>
Out merge(In1,In1,In2,In2,Out);
 
By both of them.


Mergeable{Out, In1, In2} merge(In1, In1, In2, In2, Out);

That is, you define `Mergeable` such that it is the output type. So it's not some special syntax that begins a template function declaration. It behaves no differently than any other use of a concept for a function's output parameter, while simultaneously naming some of its template parameters for use as function parameter types.


And it will surely clash with any anonymous structures return syntax, some of which are already proposed.
After all, it already looks like some class that it is returned. That is the problem with doing too much with too few words.

In any case 

Output_it copy(Input_it, Input_it, Output_it); 

is miles better (clear) then

Output_it{O} copy(Input_it{I}, I, O);  

Although it is longer. 

Same for the classical syntax

template<Output_it O, Input_it I
copy(I, I, O);  

Bengt Gustafsson

unread,
Jun 20, 2018, 6:00:08 PM6/20/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com
Is it really true that a concept can call any constexpr function? If so, how can it be used to disambiguate function overloading? Isn't a big part of concepts to be able to overload on, say, whether a container has a find method? If so, the compiler will have to check "inside" the constexpr expression to see which one is _more specialized_. For me this point has always been the problematic part of "new" concepts, the tension between being able to discern which of two true return values comes from a _more specialized_ constexpr expression, or whether this can't be deduced and the call is to be deemed ambiguous. Setting up clear rules for this seems daunting (much more so than for the old concepts pre-2011).

Thoughts?

Aarón Bueno Villares

unread,
Jun 20, 2018, 9:17:15 PM6/20/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com
I'm not an expert but in my point of view, in order to don't adding too much verbosity or new syntax elements under the "time-traveler" approach, I think C++ has already constructs enough to implement concepts without changing template syntax too much. As a C++ user since at least 10 years ago, something like this will be good enough for me without confusing the alleged time-traveler:

   template<class T> // `T` refers to the type being checked.
   concept my_concept
   {
         // Anything that can be declared inside classes.

         static bool requires() { // `requires` it's a keyword but only as a concept function member.
             // expressions that must compile with usual C++ syntax.
             // No need for `return statements`. If a call to `requires()` compiles, it returns true.
         } // Of course, any future syntactic sugar can still be applied over this base syntax which for now adds nothing new but the keyword `concept`.
   };

   template<class T>
   void f(my_concept<T> const& a) { do_whatever_with_a(); }

Here, when calling `f` with anytype, the compiler must first call `a.requires();`, and, if it compiles, then the concept is satisfied. The syntax is the same as has been always be. If there's further improvements or simplifications in template or concept syntax, it is applied all the same to functions, classes and concepts. The problem with concepts having its own syntax is that it must be treated or re-thinked separatedly for any change on the language.

The adventage of defining concepts as some kind of metaclasses, is that you can declare attributes, static functions, using-declarations and anything that helps you to write your requires expressions in a more readable way, or do anything that can be currently done with classes, like writting partial specializations, inheritance of concepts or defining local (auxiliary) concepts. Any future change to the core language, can be applied and being used in metaclasses as well. So, syntactic concerns about concepts can be left to future discussions, and the language could add concepts "right know". The only concerns are semantical, not syntactical.

When the time-traveler reads `my_concept` he will initially think `my_concept` is a class that must be defined somewhere, with no further misunderstandings because there's no extra syntax; and then he founds `concept`. The time-traveler just googles it and will easily understand what is going on.

In case you need a manual check of a constraint, you can just do: `if constexpr (concept_a<T>::requires()) bla_bla_bla();`.

About future improvements, another thing that worries me is about the extra compilation step to check concepts. For example, standard library components will be implemented in such a way that will satisfy for sure certain concepts. Having to check the same contrainsts over and over again with types that we already know will satisfy them is a waste. This can be also applied to user-defined types that have been fully tested.

So maybe any mechanism to declare that a class satisfies a concept would be a good think. To don't adding new syntaxes for that, let's just keep using the functional notation, with a colon to identify it as a keyword (emacs-lisp style):

    struct A
    {
         bool :satisfies(destructible<T> const&) { return true; } // constexpr is mandatory, and then, implicit.
         bool :satisfies(iterable<T> const&) { return false; } // SFINAE purposes with fast compilation times for known contexts?
    };

If you instantiate a function using an object of type `A`, and the function requires it is `destructible`, you promises that `A` already satisfies it and then the `requires` check of the function parameter can be skipped to improve compilation times. If you lied, you will get the usual compiler errors in the instantiation steps.

Of course, if a `satisfability` assertion rest on dependent types, you can use `if constexpr` constructs to computate the result (or just use `if`; `constexpr` is implicit inside `:satisfies`).

If later you want to reduce typing when declaring constraints (like the already know `requires` clauses in function signatures), the language should just use syntactic sugar over the standard approach (a `concept` class is automatically created with the usual members described above; like it's already done with `lambda` expressions).

Each time I read about future purposal on concepts and templates, usually the discussions are mixed: in one hand, we have the problem of template verbosity, and on the other hand, how to add concepts to the language, and the discussions tries to solve both problems at once.

I think that way of expressing concepts allow more separation of concerns. You add concepts capabilities to the language using the already existing syntax with just a couple of keywords. Then, you can apply any liked syntactic sugar on template declarations in an independent way (which will affect the expressibility of concepts as well), and later, based on the agreed template simplifications, then any specific syntactic sugar for concepts.


floria...@gmail.com

unread,
Jun 21, 2018, 4:24:29 AM6/21/18
to ISO C++ Standard - Future Proposals
The way to see if a concept is "more specialized" than another is to check if the first is a conjunction using the second.

template <class T> constexpr bool foo();
template <class T> constexpr bool bar();

template <class T> concept Foo = foo<T>();
template <class T> concept FooBar = Foo<T> && bar<T>();

Here FooBar is necessarily more specialized than Foo: There is no way that a type can satisfy FooBar, without satisfying Foo.
In theory, it could also work in the opposite way with disjunction, but I don't remember if that's a thing.

mihailn...@gmail.com

unread,
Jun 21, 2018, 10:55:38 AM6/21/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com
Ok, I was reading some old papers on the then-called Concepts Light and then it hit me.  

Terse syntax have nothing to do with Concepts! And It never had. It was a feature creep from the beginning, an additional goal, the goal to have generic code expressed naturally.

This goal however has nothing to do with Concepts as the goal for Concepts is to have constrained types and nothing more. 

The goal of generic code expressed naturally is unrelated - you might want unconstrained types expressed naturally. 

But, before concepts we didn't have "natural" templates! We didn't have func(auto) or some  func(class{}) for 30 years

This is were ALL the problems stem from - the fact we try to "evolve" natural syntax, but there is no base to evolve from!

As a result we create jump, a discontinuation, which either leads to the so called "natural" syntax looking more alien then templates themselves (incl. introducing new constructs).
or
We got confused "is auto func(Searchabe&)"  a template. It is normal to be confused - there is no continuous evolution. We/some resist the discontinuation. 

On the other hand Concepts, as an integral part of the template system do fit - it is a smooth evolution in both syntax and meaning.


And it goes the other direction - because natural has nothing to do with Concepts, the syntax MUST work with unconstrained as well. We MUST have func(auto) or  func(class{T});


With all that out of the way, I intended to write a proposal to not include any terse syntax for 20. Now I don't have a shadow of doubt this is The Right Thing (for now). Luckily (not that it s luck!) the current working paper does not includes any of it.

To iterate, I am not against natural, but 
it MUST be tackled as separate problem, 
it MUST be decupled from Concepts (physically and mentally) 
it MUST be tackled AFTER Concepts and 
it MUST handle unconstrained as well. 

Nicol Bolas

unread,
Jun 21, 2018, 11:40:08 AM6/21/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com
On Thursday, June 21, 2018 at 10:55:38 AM UTC-4, mihailn...@gmail.com wrote:
Ok, I was reading some old papers on the then-called Concepts Light and then it hit me.  

Terse syntax have nothing to do with Concepts! And It never had. It was a feature creep from the beginning, an additional goal, the goal to have generic code expressed naturally.

This goal however has nothing to do with Concepts as the goal for Concepts is to have constrained types and nothing more.

That's one way to express it. Another way to express the goal of the Concepts-lite proposal is to improve the ability of users to constrain templates. That involves two pieces: how to define constraints and how to apply them. "Natural syntax" is about application, and therefore falls under its purview.

The goal of generic code expressed naturally is unrelated - you might want unconstrained types expressed naturally.

You almost never want truly unconstrained types. Seriously, show me a template that genuinely imposes no constraints on its argument. It happens, but not very often. `any`'s constructor requires that `T` is CopyConstructible. Even `emplace` requires that the sequence of parameters can be forwarded to `allocator::construct`.

We use unconstrained types mainly because constraining them requires lots of effort. The goal of concepts is to minimize that effort. The fruits of that goal is the ability to express those constraints "naturally".

So to say that constraints and "natural syntax" are unrelated is misleading. The existence of constraints makes "natural syntax" useful, readable, and digestible. And "natural syntax" makes constraint application more useable, readable, and digestible.

The two are closely associated.

Unconstrained "natural syntax" is just porting lambda's use of `auto` parameters to regular functions. And doing only that is just not worth the effort, not in a world where constraints exist as a feature.

But, before concepts we didn't have "natural" templates! We didn't have func(auto) or some  func(class{}) for 30 years

[](auto foo) {...}

This is were ALL the problems stem from - the fact we try to "evolve" natural syntax, but there is no base to evolve from!

As a result we create jump, a discontinuation, which either leads to the so called "natural" syntax looking more alien then templates themselves (incl. introducing new constructs).
or
We got confused "is auto func(Searchabe&)"  a template. It is normal to be confused - there is no continuous evolution. We/some resist the discontinuation. 

On the other hand Concepts, as an integral part of the template system do fit - it is a smooth evolution in both syntax and meaning.


And it goes the other direction - because natural has nothing to do with Concepts, the syntax MUST work with unconstrained as well. We MUST have func(auto) or  func(class{T});

Why? I mean sure, it'd be nice, but we can get unconstrained behavior with `template<typename T> concept all = true;`. I'm not formally against the use of `auto`, but that's primarily because lambdas set the precedent. Personally, if there were no generic lambdas, then I would say that `auto` is the wrong keyword because it doesn't work like `auto` normally does in deduction.

If we could switch to a named "unconstrained" constraint rather than `auto`, I think that would be better.

Also, `class` implies a constraint: that the type is a class. That's why I prefer `typename` in templates over `class`, even though they technically mean the same thing.

With all that out of the way, I intended to write a proposal to not include any terse syntax for 20. Now I don't have a shadow of doubt this is The Right Thing (for now). Luckily (not that it s luck!) the current working paper does not includes any of it.

And luckily, most of the committee seems to disagree, since they're moving forward with these proposals. I highly doubt you're going to convince them that the very idea of terse syntax is not related to concepts, or that they should abandon the idea.

To iterate, I am not against natural, but 
it MUST be tackled as separate problem, 

It already is a separate problem. Suggesting that people keep doing the thing they're already doing isn't useful.

it MUST be decupled from Concepts (physically and mentally) 

See above.

it MUST be tackled AFTER Concepts and 

We already are "AFTER Concepts".

it MUST handle unconstrained as well.

Ignoring the fact that you can have a `template<typename T> concept all = true;` to get "unconstrained", Bjarne's syntax already does. Nobody is ignoring "unconstrained" cases.

Nicol Bolas

unread,
Jun 21, 2018, 11:46:19 AM6/21/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com


On Thursday, June 21, 2018 at 11:40:08 AM UTC-4, Nicol Bolas wrote:
On Thursday, June 21, 2018 at 10:55:38 AM UTC-4, mihailn...@gmail.com wrote:
Ok, I was reading some old papers on the then-called Concepts Light and then it hit me.  

Terse syntax have nothing to do with Concepts! And It never had. It was a feature creep from the beginning, an additional goal, the goal to have generic code expressed naturally.

This goal however has nothing to do with Concepts as the goal for Concepts is to have constrained types and nothing more.

That's one way to express it. Another way to express the goal of the Concepts-lite proposal is to improve the ability of users to constrain templates. That involves two pieces: how to define constraints and how to apply them. "Natural syntax" is about application, and therefore falls under its purview.

This is a point I wanted to elaborate on further.

Concepts-lite did not have to allow this:

template<Concept T> ...;

It could have required you to use an explicit requires clause:

template<typename T> requires Concept<T> ...;

That would have been the bare minimum feature: requires clauses applying concepts.

But the proposal didn't stop there; it allowed you to apply a concept to a template parameter directly. It even implicitly instantiates that concept without needing <>. Back when function concepts were allowed/required, it even implicitly called the function.

Those are all usability enhancements: they make applying a concept to a template easier and more digestible.

Natural syntax is merely another form of usability enhancement. If the replacing of `typename` with a type concept is reasonable for Concepts-lite, then so too is the consideration of other usability enhancements. Even ones that remove `template` boilerplate.

mihailn...@gmail.com

unread,
Jun 21, 2018, 12:37:03 PM6/21/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com


On Thursday, June 21, 2018 at 6:46:19 PM UTC+3, Nicol Bolas wrote:


On Thursday, June 21, 2018 at 11:40:08 AM UTC-4, Nicol Bolas wrote:
On Thursday, June 21, 2018 at 10:55:38 AM UTC-4, mihailn...@gmail.com wrote:
Ok, I was reading some old papers on the then-called Concepts Light and then it hit me.  

Terse syntax have nothing to do with Concepts! And It never had. It was a feature creep from the beginning, an additional goal, the goal to have generic code expressed naturally.

This goal however has nothing to do with Concepts as the goal for Concepts is to have constrained types and nothing more.

That's one way to express it. Another way to express the goal of the Concepts-lite proposal is to improve the ability of users to constrain templates. That involves two pieces: how to define constraints and how to apply them. "Natural syntax" is about application, and therefore falls under its purview.

This is a point I wanted to elaborate on further.

Concepts-lite did not have to allow this:

template<Concept T> ...;

It could have required you to use an explicit requires clause:

template<typename T> requires Concept<T> ...;

That would have been the bare minimum feature: requires clauses applying concepts.

But the proposal didn't stop there; it allowed you to apply a concept to a template parameter directly. It even implicitly instantiates that concept without needing <>. Back when function concepts were allowed/required, it even implicitly called the function.

This does not introduce natural syntax. It builds on templates machinery. I am not against shortcuts. Natural is much more then that however.
 

Those are all usability enhancements: they make applying a concept to a template easier and more digestible.

Natural syntax is merely another form of usability enhancement. If the replacing of `typename` with a type concept is reasonable for Concepts-lite, then so too is the consideration of other usability enhancements. Even ones that remove `template` boilerplate.

It is obviously not that simple as "merely another form". If it was, then there would have been no issues. 
But exactly because we cross a boundary outside templates, outside what we used for 30 years, we can't agree how to proceed and the opinions vary greatly - from minimalistic to new templates syntax. 

It is better to see and accepts there is boundary, then to pretend there is some sort of "natural evolution" that happens to "suddenly" not be so natural for many people.  

<Will answer the previous post separately.>

mihailn...@gmail.com

unread,
Jun 21, 2018, 1:58:18 PM6/21/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com


On Thursday, June 21, 2018 at 6:40:08 PM UTC+3, Nicol Bolas wrote:
On Thursday, June 21, 2018 at 10:55:38 AM UTC-4, mihailn...@gmail.com wrote:
Ok, I was reading some old papers on the then-called Concepts Light and then it hit me.  

Terse syntax have nothing to do with Concepts! And It never had. It was a feature creep from the beginning, an additional goal, the goal to have generic code expressed naturally.

This goal however has nothing to do with Concepts as the goal for Concepts is to have constrained types and nothing more.

That's one way to express it. Another way to express the goal of the Concepts-lite proposal is to improve the ability of users to constrain templates. That involves two pieces: how to define constraints and how to apply them. "Natural syntax" is about application, and therefore falls under its purview.
 
Hold on, what are the two pieces. Define and Apply. "to improve the ability of users to constrain templates", where I assume natural syntax fall in is a third goal.

Because Define and Apply is already served by Concepts without natural syntax. Natural syntax is "an improvement", something additional. 


 

The goal of generic code expressed naturally is unrelated - you might want unconstrained types expressed naturally.

You almost never want truly unconstrained types. Seriously, show me a template that genuinely imposes no constraints on its argument. It happens, but not very often. `any`'s constructor requires that `T` is CopyConstructible. Even `emplace` requires that the sequence of parameters can be forwarded to `allocator::construct`.

We use unconstrained types mainly because constraining them requires lots of effort. The goal of concepts is to minimize that effort. The fruits of that goal is the ability to express those constraints "naturally".

Prototyping, teaching, consistency. Unconstrained are hare to stay as a baseline.  
 

So to say that constraints and "natural syntax" are unrelated is misleading. The existence of constraints makes "natural syntax" useful, readable, and digestible. And "natural syntax" makes constraint application more useable, readable, and digestible.

First, there is no such thing as "natural syntax" as we cant agree what it looks like. 
Second, the benefits of Concepts alone are so massive that anyone will gladly use them as they are now. 
No one, ever, will boycott them because the lack of some magical syntax. Why? Because they use the same old syntax one is using for ages! 

Natural syntax is not related to Concepts directly, it is related to Temples and generic programming. 
The desire to have natural syntax will not disappear if Concepts are not used and, with few expectations, it is not greater if Concepts are used.  
 

The two are closely associated.

Unconstrained "natural syntax" is just porting lambda's use of `auto` parameters to regular functions. And doing only that is just not worth the effort, not in a world where constraints exist as a feature.

But, before concepts we didn't have "natural" templates! We didn't have func(auto) or some  func(class{}) for 30 years

[](auto foo) {...}

This is were ALL the problems stem from - the fact we try to "evolve" natural syntax, but there is no base to evolve from!

As a result we create jump, a discontinuation, which either leads to the so called "natural" syntax looking more alien then templates themselves (incl. introducing new constructs).
or
We got confused "is auto func(Searchabe&)"  a template. It is normal to be confused - there is no continuous evolution. We/some resist the discontinuation. 

On the other hand Concepts, as an integral part of the template system do fit - it is a smooth evolution in both syntax and meaning.


And it goes the other direction - because natural has nothing to do with Concepts, the syntax MUST work with unconstrained as well. We MUST have func(auto) or  func(class{T});

Why? I mean sure, it'd be nice, but we can get unconstrained behavior with `template<typename T> concept all = true;`. I'm not formally against the use of `auto`, but that's primarily because lambdas set the precedent. Personally, if there were no generic lambdas, then I would say that `auto` is the wrong keyword because it doesn't work like `auto` normally does in deduction.

If we could switch to a named "unconstrained" constraint rather than `auto`, I think that would be better.

Also, `class` implies a constraint: that the type is a class. That's why I prefer `typename` in templates over `class`, even though they technically mean the same thing.

With all that out of the way, I intended to write a proposal to not include any terse syntax for 20. Now I don't have a shadow of doubt this is The Right Thing (for now). Luckily (not that it s luck!) the current working paper does not includes any of it.

And luckily, most of the committee seems to disagree, since they're moving forward with these proposals. I highly doubt you're going to convince them that the very idea of terse syntax is not related to concepts, or that they should abandon the idea.


They agree, there is a clear boundary. They can't agree on syntax and the differences are not minor, but major, diametrical. 
Natural syntax is only partially related to Concepts, and is bigger then we think - it does not flow naturally (that much was proven), it must be invented, it is a different topic. 
I am not for abandoned, but for it to be separate topic, not against current Concepts WP and on later date so the 99% can give feedback. 

 

To iterate, I am not against natural, but 
it MUST be tackled as separate problem, 

It already is a separate problem. Suggesting that people keep doing the thing they're already doing isn't useful.

it MUST be decupled from Concepts (physically and mentally) 

See above.


Then why are natural syntax proposals against Concepts WP? 
Why it is officially listed as "issues with Concepts".

 
it MUST be tackled AFTER Concepts and 

We already are "AFTER Concepts".

Are we? 
Concepts are not only not released, they are still worked on. And by worked on I mean real issues like the Constraining Concepts Overload Sets proposal
 

it MUST handle unconstrained as well.

Ignoring the fact that you can have a `template<typename T> concept all = true;` to get "unconstrained", Bjarne's syntax already does. Nobody is ignoring "unconstrained" cases.
 
We are playing with words - is 'unconstrained' no concept or concepts which accept everything. That's an interesting question. 
Should unconstrained be expressed in terms of Concepts? Should we deprecate class/typename or auto as arg? 
Fact of the matter is we often completely ignore the unconstrained case.



Nicol Bolas

unread,
Jun 21, 2018, 4:05:17 PM6/21/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com
On Thursday, June 21, 2018 at 12:37:03 PM UTC-4, mihailn...@gmail.com wrote:
On Thursday, June 21, 2018 at 6:46:19 PM UTC+3, Nicol Bolas wrote:
On Thursday, June 21, 2018 at 11:40:08 AM UTC-4, Nicol Bolas wrote:
On Thursday, June 21, 2018 at 10:55:38 AM UTC-4, mihailn...@gmail.com wrote:
Ok, I was reading some old papers on the then-called Concepts Light and then it hit me.  

Terse syntax have nothing to do with Concepts! And It never had. It was a feature creep from the beginning, an additional goal, the goal to have generic code expressed naturally.

This goal however has nothing to do with Concepts as the goal for Concepts is to have constrained types and nothing more.

That's one way to express it. Another way to express the goal of the Concepts-lite proposal is to improve the ability of users to constrain templates. That involves two pieces: how to define constraints and how to apply them. "Natural syntax" is about application, and therefore falls under its purview.

This is a point I wanted to elaborate on further.

Concepts-lite did not have to allow this:

template<Concept T> ...;

It could have required you to use an explicit requires clause:

template<typename T> requires Concept<T> ...;

That would have been the bare minimum feature: requires clauses applying concepts.

But the proposal didn't stop there; it allowed you to apply a concept to a template parameter directly. It even implicitly instantiates that concept without needing <>. Back when function concepts were allowed/required, it even implicitly called the function.

This does not introduce natural syntax. It builds on templates machinery. I am not against shortcuts. Natural is much more then that however.
 

Those are all usability enhancements: they make applying a concept to a template easier and more digestible.

Natural syntax is merely another form of usability enhancement. If the replacing of `typename` with a type concept is reasonable for Concepts-lite, then so too is the consideration of other usability enhancements. Even ones that remove `template` boilerplate.

It is obviously not that simple as "merely another form". If it was, then there would have been no issues. But exactly because we cross a boundary outside templates, outside what we used for 30 years, we can't agree how to proceed and the opinions vary greatly - from minimalistic to new templates syntax.

Let me see if I've got this right. Terse syntax is not "merely another form" of usability enhancements. Why? Because if it trust were just that, there wouldn't be arguments about what form it should take.

By that reasoning, `template<Concept T>` is not "merely another form" either. Why? Because we have people in this very thread who have argued that it ought to be `template<auto<Concept> T>`. There have been actual proposals for `template<Concept typename T>` (thankfully, they were expurgated). So there are arguments about what this form should take.

And therefore, by your reasoning, it is not "merely another form" of "Apply". So which is it? Will you accept that we should also ditch `template<Concept T>`? Or can we agree that disagreement alone does not represent some kind of "boundary outside template"?

It is better to see and accepts there is boundary, then to pretend there is some sort of "natural evolution" that happens to "suddenly" not be so natural for many people.

Nobody is "suddenly" anything. People have had concerns about Bjarne's "natural syntax" since its inception.

On Thursday, June 21, 2018 at 1:58:18 PM UTC-4, mihailn...@gmail.com wrote:
On Thursday, June 21, 2018 at 6:40:08 PM UTC+3, Nicol Bolas wrote:
On Thursday, June 21, 2018 at 10:55:38 AM UTC-4, mihailn...@gmail.com wrote:
Ok, I was reading some old papers on the then-called Concepts Light and then it hit me.  

Terse syntax have nothing to do with Concepts! And It never had. It was a feature creep from the beginning, an additional goal, the goal to have generic code expressed naturally.

This goal however has nothing to do with Concepts as the goal for Concepts is to have constrained types and nothing more.

That's one way to express it. Another way to express the goal of the Concepts-lite proposal is to improve the ability of users to constrain templates. That involves two pieces: how to define constraints and how to apply them. "Natural syntax" is about application, and therefore falls under its purview.

Hold on, what are the two pieces. Define and Apply. "to improve the ability of users to constrain templates", where I assume natural syntax fall in is a third goal.

You misunderstood my meaning. "To improve the ability of users to constrain templates" is why concepts exists at all. It is the very goal of concepts.

"Define and Apply" are the means to achieve that goal; they are not the goal itself. My point is that "natural syntax" is within that goal; therefore, it is a perfectly reasonable thing for the Concepts proposal to include. It is not out-of-bounds, it is not scope creep or anything of the sort.

The goal of generic code expressed naturally is unrelated - you might want unconstrained types expressed naturally.

You almost never want truly unconstrained types. Seriously, show me a template that genuinely imposes no constraints on its argument. It happens, but not very often. `any`'s constructor requires that `T` is CopyConstructible. Even `emplace` requires that the sequence of parameters can be forwarded to `allocator::construct`.

We use unconstrained types mainly because constraining them requires lots of effort. The goal of concepts is to minimize that effort. The fruits of that goal is the ability to express those constraints "naturally".

Prototyping, teaching, consistency. Unconstrained are hare to stay as a baseline.

Where I come from, you start by creating an interface. In class hierarchies, that means a base class with pure virtual functions. With static polymorphism, that now means creating a concept.

Any good teacher should start teaching static polymorphism with concepts. New users should be taught that unconstrained templates exist but should be avoided. And any decent prototype will have a prototype interface too, expressed as a concept.

Now sure, you're still going to need `<typename T>`, but this will be for cases where `T` needs to be constrained by a `requires` clause. Truly unconstrained template parameters ought to go the way of the Dodo.

So to say that constraints and "natural syntax" are unrelated is misleading. The existence of constraints makes "natural syntax" useful, readable, and digestible. And "natural syntax" makes constraint application more useable, readable, and digestible.

First, there is no such thing as "natural syntax" as we cant agree what it looks like.

Yes there is. The term "natural syntax" comes directly from Bjarne Stroustrup and specifically refers to the Concepts TS proposal's terse syntax. Indeed, you were the first one to bring the term up, precisely because the early Concepts TS proposals referred to that syntax as "natural syntax".

What is being debated by the committee is what terse syntax will look like: Bjarne's "natural syntax" or Herb's alternative form.

And even then, there is clear agreement on the basic principle behind terse templates: you replace a parameter typename and/or output value with a concept name; this causes the parameter/output value to be deduced via a constrained template/return value deduction. So the general look of the concept is well understood. The differences, while significant, are not that huge.

Second, the benefits of Concepts alone are so massive that anyone will gladly use them as they are now. 
No one, ever, will boycott them because the lack of some magical syntax. Why? Because they use the same old syntax one is using for ages!

Who are you arguing with? Nobody claimed that people would avoid concepts because of a lack of "natural syntax". Just because people will use a feature anyway does not mean we can't make it more readable and easier to use.

Producing the bare minimum when you can do more and better than that doesn't make sense.

Natural syntax is not related to Concepts directly, it is related to Temples and generic programming. 
The desire to have natural syntax will not disappear if Concepts are not used and, with few expectations, it is not greater if Concepts are used.
 
With all that out of the way, I intended to write a proposal to not include any terse syntax for 20. Now I don't have a shadow of doubt this is The Right Thing (for now). Luckily (not that it s luck!) the current working paper does not includes any of it.

And luckily, most of the committee seems to disagree, since they're moving forward with these proposals. I highly doubt you're going to convince them that the very idea of terse syntax is not related to concepts, or that they should abandon the idea.

They agree, there is a clear boundary.

No, they agree that terse syntax needs more discussion and has issues to be worked out compared to the rest of concepts.

They did not agree that terse syntax is unrelated to concepts, or that terse syntax should be abandoned or delayed.

They can't agree on syntax and the differences are not minor, but major, diametrical.

"Can't" is a far cry from "haven't". The latter is true; the former has yet to be determined.
 
Natural syntax is only partially related to Concepts, and is bigger then we think - it does not flow naturally (that much was proven), it must be invented, it is a different topic. 
I am not for abandoned, but for it to be separate topic, not against current Concepts WP and on later date so the 99% can give feedback.

Who is this 99% who are incapable of giving feedback on Concepts TS, but will be capable of giving feedback in a few years? Indeed, the entire terse syntax discussion is feedback on the "natural syntax" in Concepts TS.

Why is that feedback insufficient? Why do you treat terse syntax as though it's some novel thing that nobody has ever heard of before? It's been over four years since the concepts-lite effort started.

To iterate, I am not against natural, but 
it MUST be tackled as separate problem, 

It already is a separate problem. Suggesting that people keep doing the thing they're already doing isn't useful.

it MUST be decupled from Concepts (physically and mentally) 

See above.


Then why are natural syntax proposals against Concepts WP?

I don't know what you mean by "Concepts WP". The terse syntax proposals are EWG proposals, not proposals against the Concepts TS.

Why it is officially listed as "issues with Concepts".

Because terse templates come from the Concepts TS. Therefore, adjustments to issues relating to the Concepts TS are issues with concepts.

it MUST be tackled AFTER Concepts and 

We already are "AFTER Concepts".

Are we?
Concepts are not only not released, they are still worked on. And by worked on I mean real issues like the Constraining Concepts Overload Sets proposal

We are as "AFTER Concepts" as it is reasonable to get. Unless you are suggesting that there will be design changes to concepts that will impact terse syntax, there is no problem moving forward with both terse syntax discussions and tweaks to the concepts feature.

Again, I don't know what it is that you're so concerned about here. What are you afraid will happen if the committee continues to debate these proposals (besides your technical issues with Herb's proposal)? Why do you feel it is necessary to shut down all discussion in this area?

mihailn...@gmail.com

unread,
Jun 22, 2018, 3:13:29 AM6/22/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com


On Thursday, June 21, 2018 at 11:05:17 PM UTC+3, Nicol Bolas wrote:
On Thursday, June 21, 2018 at 12:37:03 PM UTC-4, mihailn...@gmail.com wrote:
On Thursday, June 21, 2018 at 6:46:19 PM UTC+3, Nicol Bolas wrote:
On Thursday, June 21, 2018 at 11:40:08 AM UTC-4, Nicol Bolas wrote:
On Thursday, June 21, 2018 at 10:55:38 AM UTC-4, mihailn...@gmail.com wrote:
Ok, I was reading some old papers on the then-called Concepts Light and then it hit me.  

Terse syntax have nothing to do with Concepts! And It never had. It was a feature creep from the beginning, an additional goal, the goal to have generic code expressed naturally.

This goal however has nothing to do with Concepts as the goal for Concepts is to have constrained types and nothing more.

That's one way to express it. Another way to express the goal of the Concepts-lite proposal is to improve the ability of users to constrain templates. That involves two pieces: how to define constraints and how to apply them. "Natural syntax" is about application, and therefore falls under its purview.

This is a point I wanted to elaborate on further.

Concepts-lite did not have to allow this:

template<Concept T> ...;

It could have required you to use an explicit requires clause:

template<typename T> requires Concept<T> ...;

That would have been the bare minimum feature: requires clauses applying concepts.

But the proposal didn't stop there; it allowed you to apply a concept to a template parameter directly. It even implicitly instantiates that concept without needing <>. Back when function concepts were allowed/required, it even implicitly called the function.

This does not introduce natural syntax. It builds on templates machinery. I am not against shortcuts. Natural is much more then that however.
 

Those are all usability enhancements: they make applying a concept to a template easier and more digestible.

Natural syntax is merely another form of usability enhancement. If the replacing of `typename` with a type concept is reasonable for Concepts-lite, then so too is the consideration of other usability enhancements. Even ones that remove `template` boilerplate.

It is obviously not that simple as "merely another form". If it was, then there would have been no issues. But exactly because we cross a boundary outside templates, outside what we used for 30 years, we can't agree how to proceed and the opinions vary greatly - from minimalistic to new templates syntax.

Let me see if I've got this right. Terse syntax is not "merely another form" of usability enhancements. Why? Because if it trust were just that, there wouldn't be arguments about what form it should take.

By that reasoning, `template<Concept T>` is not "merely another form" either. Why? Because we have people in this very thread who have argued that it ought to be `template<auto<Concept> T>`. There have been actual proposals for `template<Concept typename T>` (thankfully, they were expurgated). So there are arguments about what this form should take.

And therefore, by your reasoning, it is not "merely another form" of "Apply". So which is it? Will you accept that we should also ditch `template<Concept T>`? Or can we agree that disagreement alone does not represent some kind of "boundary outside template"?

The boundary is obvious - addition (requires) and improvement (<Concept T>) to the current generic programing on one side, with (very) minor disagreement 
VS new way of defining generic functions, where the disagreements is massive.
 

It is better to see and accepts there is boundary, then to pretend there is some sort of "natural evolution" that happens to "suddenly" not be so natural for many people.

Nobody is "suddenly" anything. People have had concerns about Bjarne's "natural syntax" since its inception.

On Thursday, June 21, 2018 at 1:58:18 PM UTC-4, mihailn...@gmail.com wrote:
On Thursday, June 21, 2018 at 6:40:08 PM UTC+3, Nicol Bolas wrote:
On Thursday, June 21, 2018 at 10:55:38 AM UTC-4, mihailn...@gmail.com wrote:
Ok, I was reading some old papers on the then-called Concepts Light and then it hit me.  

Terse syntax have nothing to do with Concepts! And It never had. It was a feature creep from the beginning, an additional goal, the goal to have generic code expressed naturally.

This goal however has nothing to do with Concepts as the goal for Concepts is to have constrained types and nothing more.

That's one way to express it. Another way to express the goal of the Concepts-lite proposal is to improve the ability of users to constrain templates. That involves two pieces: how to define constraints and how to apply them. "Natural syntax" is about application, and therefore falls under its purview.

Hold on, what are the two pieces. Define and Apply. "to improve the ability of users to constrain templates", where I assume natural syntax fall in is a third goal.

You misunderstood my meaning. "To improve the ability of users to constrain templates" is why concepts exists at all. It is the very goal of concepts.

"Define and Apply" are the means to achieve that goal; they are not the goal itself. My point is that "natural syntax" is within that goal; therefore, it is a perfectly reasonable thing for the Concepts proposal to include. It is not out-of-bounds, it is not scope creep or anything of the sort.

What is in or out of bounds depends on the point of view as the goals are achieved without natural. 
For you, to have natural is a worthy goal, "to finish things up", for me is barely related bonus which brings downsides as well.

 

The goal of generic code expressed naturally is unrelated - you might want unconstrained types expressed naturally.

You almost never want truly unconstrained types. Seriously, show me a template that genuinely imposes no constraints on its argument. It happens, but not very often. `any`'s constructor requires that `T` is CopyConstructible. Even `emplace` requires that the sequence of parameters can be forwarded to `allocator::construct`.

We use unconstrained types mainly because constraining them requires lots of effort. The goal of concepts is to minimize that effort. The fruits of that goal is the ability to express those constraints "naturally".

Prototyping, teaching, consistency. Unconstrained are hare to stay as a baseline.

Where I come from, you start by creating an interface. In class hierarchies, that means a base class with pure virtual functions. With static polymorphism, that now means creating a concept.

Any good teacher should start teaching static polymorphism with concepts. New users should be taught that unconstrained templates exist but should be avoided. And any decent prototype will have a prototype interface too, expressed as a concept.

Now sure, you're still going to need `<typename T>`, but this will be for cases where `T` needs to be constrained by a `requires` clause. Truly unconstrained template parameters ought to go the way of the Dodo.

As I said that's an interesting topic. Should we declare typename/class legacy and advocate the 'all' concept? Should we indeed teach against concepts right away? 
For prototyping/experimenting/learning unconstrained will be used, I believe. 
 

So to say that constraints and "natural syntax" are unrelated is misleading. The existence of constraints makes "natural syntax" useful, readable, and digestible. And "natural syntax" makes constraint application more useable, readable, and digestible.

First, there is no such thing as "natural syntax" as we cant agree what it looks like.

Yes there is. The term "natural syntax" comes directly from Bjarne Stroustrup and specifically refers to the Concepts TS proposal's terse syntax. Indeed, you were the first one to bring the term up, precisely because the early Concepts TS proposals referred to that syntax as "natural syntax".

What is being debated by the committee is what terse syntax will look like: Bjarne's "natural syntax" or Herb's alternative form.

And even then, there is clear agreement on the basic principle behind terse templates: you replace a parameter typename and/or output value with a concept name; this causes the parameter/output value to be deduced via a constrained template/return value deduction. So the general look of the concept is well understood. The differences, while significant, are not that huge.

Second, the benefits of Concepts alone are so massive that anyone will gladly use them as they are now. 
No one, ever, will boycott them because the lack of some magical syntax. Why? Because they use the same old syntax one is using for ages!

Who are you arguing with? Nobody claimed that people would avoid concepts because of a lack of "natural syntax". Just because people will use a feature anyway does not mean we can't make it more readable and easier to use.

Producing the bare minimum when you can do more and better than that doesn't make sense.

Natural syntax is not related to Concepts directly, it is related to Temples and generic programming. 
The desire to have natural syntax will not disappear if Concepts are not used and, with few expectations, it is not greater if Concepts are used.
 
With all that out of the way, I intended to write a proposal to not include any terse syntax for 20. Now I don't have a shadow of doubt this is The Right Thing (for now). Luckily (not that it s luck!) the current working paper does not includes any of it.

And luckily, most of the committee seems to disagree, since they're moving forward with these proposals. I highly doubt you're going to convince them that the very idea of terse syntax is not related to concepts, or that they should abandon the idea.

They agree, there is a clear boundary.

No, they agree that terse syntax needs more discussion and has issues to be worked out compared to the rest of concepts.
 
Of course there is a boundary, C++ extensions for Concepts (Concepts WP) is chopped from Concepts TS at exactly that boundary.
 

They did not agree that terse syntax is unrelated to concepts, or that terse syntax should be abandoned or delayed.

They can't agree on syntax and the differences are not minor, but major, diametrical.

"Can't" is a far cry from "haven't". The latter is true; the former has yet to be determined.
 
Natural syntax is only partially related to Concepts, and is bigger then we think - it does not flow naturally (that much was proven), it must be invented, it is a different topic. 
I am not for abandoned, but for it to be separate topic, not against current Concepts WP and on later date so the 99% can give feedback.

Who is this 99% who are incapable of giving feedback on Concepts TS, but will be capable of giving feedback in a few years? Indeed, the entire terse syntax discussion is feedback on the "natural syntax" in Concepts TS.
 
The 99% of the C++ users have not touched or seen Concepts in any form. 
 

Why is that feedback insufficient? Why do you treat terse syntax as though it's some novel thing that nobody has ever heard of before? It's been over four years since the concepts-lite effort started.

To iterate, I am not against natural, but 
it MUST be tackled as separate problem, 

It already is a separate problem. Suggesting that people keep doing the thing they're already doing isn't useful.

it MUST be decupled from Concepts (physically and mentally) 

See above.


Then why are natural syntax proposals against Concepts WP?

I don't know what you mean by "Concepts WP". The terse syntax proposals are EWG proposals, not proposals against the Concepts TS.

Why it is officially listed as "issues with Concepts".

Because terse templates come from the Concepts TS. Therefore, adjustments to issues relating to the Concepts TS are issues with concepts.

it MUST be tackled AFTER Concepts and 

We already are "AFTER Concepts".

Are we?
Concepts are not only not released, they are still worked on. And by worked on I mean real issues like the Constraining Concepts Overload Sets proposal

We are as "AFTER Concepts" as it is reasonable to get. Unless you are suggesting that there will be design changes to concepts that will impact terse syntax, there is no problem moving forward with both terse syntax discussions and tweaks to the concepts feature.

Again, I don't know what it is that you're so concerned about here. What are you afraid will happen if the committee continues to debate these proposals (besides your technical issues with Herb's proposal)? Why do you feel it is necessary to shut down all discussion in this area?

What I am afraid is doing harm. Doing harm for a bonus feature is even worse. I believe most, no, all, of current terse syntax proposals do some harm. 

Specifically. 
A. Name introducers in any form are a harm. They are a harm because 1. they de facto create new language 2. Are not "natural". 3. In some forms are not better then the alternative.
B. Syntax-for-humans is a harm and is doomed to be attacked by counter proposals for decades.  

As I said, I am not against natural syntax in the form find(Searchable&) but it seems there is some strong opposition ageist this OR some fears. Not sure which one of the two.

And for the matter of fact am not against Herb proposal in general, I am against it being sold as "natural evolution", where in reality it is a new language. 
New language with new possibilities, no matter we like it or not: typename{T}, Container{C=std::vector}, concept{T} all = true;
These will be coming.
Herb's proposal should be evaluated on a bigger context. To adopted something on that scale just to get a bonus feature will be a mistake. 

Corentin

unread,
Jun 26, 2018, 4:07:36 AM6/26/18
to std-pr...@isocpp.org, mihailn...@gmail.com
I wrote an article on convenient syntaxes https://cor3ntin.github.io/posts/concepts_syntax/
Hopefully, the relatively thorough comparison and background may help some people.

The article features a quick poll as I attempt to get a feeling of what people think of these syntaxes, maybe it can inform the discussion.
 

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.

To post to this group, send email to std-pr...@isocpp.org.

jeanmichae...@gmail.com

unread,
Jun 28, 2018, 9:02:38 AM6/28/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com
> This code is clear to ANYONE who EVER worked with C++, even to a time traveler from 30 years ago!

I've worked with C++ and it is entirely clear to me. It will be also extremely clear to anyone having ever worked with a ML-like language.

> First Comparable_ can be confused with a return type when one starts to read.

... and what's the problem ? It means that the function returns a type that is comparable - that's hundred of miles better than whatever trickery with enable_if one could devise.

> Second The syntax is COMPLETELY alien to templates - de facto new language.

Is it ? Lambdas work exactly like this : [] (auto x) { } - it's clear for everyone having read about them that it is equivalent to struct _anon {  template<typename T> void operator()(T x) { } };

> Third there is no obvious connection b/w the function and the clause  - it just sits there like a separate declaration

that's like saying that in

    int
    foo(int x);

there's no obvious connection between the return type and the function name

> Forth Automatic names introductions is very uncommon and will be confusing for sure.

no.

It seems that you would like to keep C++ as a walled garden for experts that get high by typing pages upon pages of template<std::enable_if_t<std::complicated_sfinae_expression(decltype(typename T::whatever{}))...

Please don't. That's why so many people spit on C++ as a language, and for once there  is an opportunity to make it simpler. You sound just like these people who insisted for a complicated syntax for templates in thirty years ago while Bjarne advocated for the much saner void f<T>(T x) { }.
There's an historical chance to correct this mistake, right here.

On Tuesday, June 19, 2018 at 11:33:54 AM UTC+2, mihailn...@gmail.com wrote:
OK, right now in flight are about FOUR proposals, trying to "simplify" and "make more clear" concepts usage.

This is madness. It is madness, because NONE of it make it more clear! None. 

By inviting new language constructs one does not make things "more clear", it only adds more things to learn.

The worst part is - we have working solution that is clear. Granted verbose, but clear. 

If one makes it Not verbose but Not clear (not self-explanatory, need learning) also one gains nothing! 


Consider

template<Iterator Iter1, Iterator Iter2> 
     requires Comparable_though_iterators<Iter1, Iter2>
bool equal(Iter1 first, Iter1 last, Iter2) 
{} 

This code is clear to ANYONE who EVER worked with C++, even to a time traveler from 30 years ago!

Comparable_through_iterators{Iter1,Iter2} 
bool equal(Iter1 first, Iter1 last, Iter2) 
{} 

This is NOT clear

First Comparable_ can be confused with a return type when one starts to read. 
Second The syntax is COMPLETELY alien to templates - de facto new language. 
Third there is no obvious connection b/w the function and the clause  - it just sits there like a separate declaration
Forth Automatic names introductions is very uncommon and will be confusing for sure.

The gain of one-less-line is DWARFED by the HEAP of "new stuff" that does NOT grant "new powers"!


 --- Let's continue


Between 

void sort(Sortable& s);  

and

template void sort(Sortable& s); 

The second is more confusing! Why? Because it abuses an already established syntax for something completely different. 

Is the first confusing? Might be. What is the solution?

Solution 1:

If this is your code, and you might be confused - don't use it, use the more verbose, but more clear syntax!

Solution 2:

Just ctrl-click on Sortable (hell, just hover over it) and all you doubts will be solved! 


Inventing completely new syntax in the form of  Sortable{} is even worse:

Consider 

Number x{};
[](Number{} x) 
{}
[x = Number{}]()
{} 

Again, any gains are dwarfed by introducing new syntax to learn and/or new ways to read old constructs! 
And the biggest problem is - that syntax right now donates an action and here it will not, it will be just an indicator! 


 --- Let's continue further

Another non-issue is "the problem one cannot differentiate b/w constrained value and a type concept" 

template<Concept T, Value v> void f() {}

Why this is non-issue? 

First Because templates are inline, usage is visible and Types and Value are used RADICALLY differently.
In real word it will always be clear which is which! 

Second as already mentioned in one of the papers - one can use a naming convection.

Third the more verbose syntax (the a requires clause) is still available! 

And BTW lets not forget we have class template arguments now, so the template arguments are bound to be a bit overloaded now!

template<Concept T, Value v, Class c> void f() {}

Nothing wrong with that - we can use naming conventions and we have good IDEs to help us - no need for syntax noise.  


The Solution To All This


For now, include only the syntax clear to a time traveler! Do not include ANYTHING new to learn! 

We are JUST introducing Concepts to the general public - that alone is enough new  material!

For Simple cases

template<Sortable S> 
void sort(S& s); 

For Complex cases

template<Iterator Iter1, Iterator Iter2> 
     requires Comparable_though_iterators<Iter1, Iter2>
bool equal(Iter1 first, Iter1 last, Iter2) 
{} 

      THATS IT. DONE. 

No
template void sort(Sortable& s); 

No
void sort(Sortable{}& s); 

No 
template<Arithmetic{N}, Arithmetic {} n> void f(N);

No
template<auto Arithmetic N> void f();

No
template<Comparable_through_iterators{Iter1,Iter2}>
bool equal(Iter1 first, Iter1 last, Iter2) 
{} 

And HELL No
Comparable_through_iterators{Iter1,Iter2} 
bool equal(Iter1 first, Iter1 last, Iter2) 
{} 

Why?

A. Because of the time traveler!!!

B. Let the users have theirs say IN THE REAL WORD.

C. We can ALWAYS add "simpler" syntax later, say in 5 years!


Future Directions

Why not let arguments be comma separated lists if we care so much about typing

template<class In1, In2, Out> 
   requires Mergeable<In1, In2, Out>  
Out merge(In1,In1,In2,In2,Out);

Why not instead of the new syntax for names introducing we simply

Tony V E

unread,
Jun 28, 2018, 1:05:19 PM6/28/18
to Standard Proposals, Михаил Найденов
For some, terse syntax points out problems with the non-terse syntax - whether we ever get terse syntax or not.  So we should probably tackle that now.
In particular,

template <X x>

Some would prefer that x is a value, not a type, regardless to whether X is a type or a concept.


it MUST be decupled from Concepts (physically and mentally) 
it MUST be tackled AFTER Concepts and 
it MUST handle unconstrained as well. 

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.

To post to this group, send email to std-pr...@isocpp.org.

Nicol Bolas

unread,
Jun 28, 2018, 1:40:14 PM6/28/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com, jeanmichae...@gmail.com
I make no defense of the OP's argument, but he is not talking stating that we shouldn't have concepts at all (and thus must continue to use `std::enable_if` gymnastics). He's talking specifically and only about terse syntax for declaring conceptualized template functions.

He's saying that we're better off using explicit `requires` clauses than having shorter syntax. He's not saying that we're better off with `enable_if`".

Arthur O'Dwyer

unread,
Jun 28, 2018, 8:33:29 PM6/28/18
to ISO C++ Standard - Future Proposals, mihailn...@gmail.com, jeanmichae...@gmail.com
On Thursday, June 28, 2018 at 10:40:14 AM UTC-7, Nicol Bolas wrote:
I make no defense of the OP's argument, but he is not talking stating that we shouldn't have concepts at all (and thus must continue to use `std::enable_if` gymnastics). He's talking specifically and only about terse syntax for declaring conceptualized template functions.

He's saying that we're better off using explicit `requires` clauses than having shorter syntax. He's not saying that we're better off with `enable_if`".

Right. I, also, strongly support the new `requires` keyword, while being skeptical of not only terse syntax but also Concepts Lite in general.
I highly recommend anyone interested in Concepts read these two short position papers:


Ville's paper isn't really asking for Concepts, and certainly not for terse syntax; he's asking only for the `requires` keyword (although he conflates it with "Concepts" as a whole, because that was the all-or-nothing zeitgeist at the time). Here's the benefits he lists:
Matt's paper is also asking for the `requires` keyword, but asking specifically that we try not to conflate the `requires` keyword with the much more controversial and less-fully-baked `concept` keyword.

And of course if `concept` itself isn't fully baked yet, naturally no terse syntax based on `concept` can be!  But, at the same time, that doesn't mean that we can't discuss things like terse syntax and so on. Most people agree that the abstract goal is nice; it's just that no good technical means has yet been devised to get us there.

–Arthur
Reply all
Reply to author
Forward
0 new messages