Discussion:
[std-proposals] Named Parameters for C++
Justin Bassett
2018-08-16 05:10:39 UTC
Permalink
I'm working on a paper to write this up more formally, but before I do
that, I wanted to share my research and work and generate some discussion.

Currently, it is possible to pass parameters by position, but not by name.
To work around this limitation, there are a multitude of solutions. A few
are listed here:

- The "Named Parameters Idiom," sometimes called the Builder Pattern.
- Boost Parameters
<https://www.boost.org/doc/libs/1_68_0/libs/parameter/doc/html/index.html>.
Overloads operator= to make it look like a named parameter.
- Boost Graph's named parameters. Parameter values are passed via member
functions.
- Strong types. This suffers from the limitation that parameters cannot
be reordered, and sometimes you'd have to create types that otherwise have
no meaning.
- Designated Initializers. There are those who hope that designated
initializers will work as named parameters, but they don't work that well.

Each of these have disadvantages. Here's a small list:

- Hard to maintain.
- Have to prefix every argument with the library's namespace, or else
use a lot of using declarations or even a using directive.
- Each argument has to be passed in order (Strong types), otherwise it's
a ton of overloads for the library author to work out.
- Possibly worse code-gen

I claim we should standardize a way of passing named arguments in C++.



Use cases for Named Parameters (aka Named Arguments, aka Keyword Arguments):

- Named-or-positional parameters.
- Name-only parameters
- Either of the above combined with default arguments



Syntax: there are two possible syntaxes I've seen that work for named
parameters in C++:

foo(.name = value)
foo(name: value)

I honestly don't care which we go for, but for consistency with designated
initializers (which may be a bad thing if the behavior is significantly
different), I'm going to choose the foo(.name = value) syntax for the time
being.

For declaring a function with named parameters, it is imperative that it is
opt-in, otherwise, functions parameter names become part of the public API
of the function, which is undesirable:

int foo(int .x);

It might be tempting to separate the name of the parameter from the name
used in named parameters, but I claim this overly repetitive. As long as
named parameters are opt-in, having to give an alternative name is
completely redundant. (I believe Swift does this)

There should be some way to specify that the parameter is name-only. For
example, altering Python's implementation
<https://www.python.org/dev/peps/pep-3102/>:

// anything after the . is name-only
int foo(., int .x);

Default arguments should be able to work as they are now.



Semantics:
It's a pretty standard rule that all named arguments must come after all
positional arguments. It is also pretty standard that named arguments can
be in a different order than in the function declaration. I don't see a
compelling reason to break from this, even though there are exceptions in
languages today (e.g. C# and Swift)

There are some options on how the named parameters should work. It could work
like C# and just reorder the arguments
<https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/named-and-optional-arguments#overload-resolution>.
However, I believe that the name should be part of the function type and
should be mangled into the name for the function. It should not be allowed
for the following two declarations to coexist:

int foo(int .x, int .y);
int foo(int .a, int .b);

If the name of the parameters are not part of the function, then if those
declarations are in separate translation units, there's little way to
enforce that this should fail to compile / link.

This does bring in the issue that it becomes harder to change existing APIs
to accept named parameters in an ABI compatible manner. For this, maybe the
compiler could emit two symbols for the named-positional argument case?
Otherwise, I think there should be some way to either cause the compiler to
emit two symbols or otherwise maintain ABI compatibility.

Now for templates. In order to have higher-order functions which work on
named parameters, I believe it is necessary to have a new kind of template
parameter, something like this:

// I separated the name completely from the type.
// This would severely complicate generic code, however, so maybe there's
// a way to keep both together
template <typename F, .typename Name, typename Arg>
void call(F fn, Arg&& .Name arg) {
// Some syntax to expand the name is needed. I'm not sure what
// a reasonable choice is. There should also probably be a way
// to generate a name from a compile time string.
fn(.(Name) = std::forward<Arg>(arg));
}

// Or maybe something combining the name and type would be better:
template <typename F, .typename Kwarg>
void call(F fn, Kwarg&& arg) {
fn(.(nameof(Kwarg)) = std::forward<Kwarg>(arg));
}

// Valid ways to call it:
call(sqrt, .x = 9);
call(sqrt, 9); // We didn't enforce name-only in the declaration of call

Reflection could possibly allow us to inspect the actual name supplied
(useful for libraries such as fmt: fmt::format("({x}, {y})", .x = 10, .y =
20); ), and it would probably be useful to be able to generate a name from
a compile-time string.

How lookup is performed: it's certainly possible to have overloaded
functions along with named parameters. I haven't spent the time yet to
flesh out all the details, but the named parameters can be each in their
own dimension, as compared to the positional dimension.



Further ideas: I don't want to propose this yet, but I would also like to
see named parameters in template parameters. For example, it would be nice
to be easily able to specify the allocator of an unordered_map:
std::unordered_map<Key,
Value, .allocator = MyAllocator> . I believe this would break ABI
compatibility, though.



Implementation:
It sounds crazy to add a new kind of template parameter and include the
name of the parameters as part of the function type, but I believe this
would be implementable with some kind of __name<"parameter_name"> type with
some connection to the regular template type, as well as some rules on
reordering (consider something like sorting all name-only parameters
lexicographically and re-mapping named-positional parameters to their
position). I won't know for sure until I attempt an implementation, but I
believe it should work.



References - some things I've found about named parameter design, which I
may have referred to in my writeup above. Most of these I didn't link to
inline:

https://www.python.org/dev/peps/pep-3102/

https://internals.rust-lang.org/t/pre-rfc-named-arguments/3831

https://internals.rust-lang.org/t/pre-rfc-named-arguments/3831/196

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/named-and-optional-arguments#overload-resolution

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4172.htm

http://jamboree.github.io/designator-draft.html

https://www.reddit.com/r/cpp/comments/5mdes5/what_happened_to_the_named_parameter_proposal/
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAPuuy5eBx1ybcPjS6dNsk7n1_c2uhdRBS19qr%3Dq5cj3cTURnLQ%40mail.gmail.com.
Nicolas Lesser
2018-08-16 05:55:12 UTC
Permalink
Post by Justin Bassett
For declaring a function with named parameters, it is imperative that it
is opt-in, otherwise, functions parameter names become part of the public
API of the function, which is undesirable
Pardon my ignorance, but why exactly is this undesirable? Designated
initializer lists are also not opt-in. I don't really see a problem with
this. I can't imagine function parameters to change once they're the
function is part of the API.

There should be some way to specify that the parameter is name-only. For
Post by Justin Bassett
example, altering Python's implementation
// anything after the . is name-only
int foo(., int .x);
Default arguments should be able to work as they are now.
I disagree with your proposed solution. Name-only parameters naturally
appear when they are after a varadic ("catch-all") parameter, just like in
Python's implementation.

template <typename ...T>
void f(T ..., int name);

f(.name = 1); // name-only argument

Now you have a small problem: C's variadic parameters are specified in the
grammar itself to come last, which can be changed but would require some
restructuring. But I don't think it's worth supporting them.

However, I believe that the name should be part of the function type and
Post by Justin Bassett
should be mangled into the name for the function. It should not be allowed
int foo(int .x, int .y);
int foo(int .a, int .b);
If the name of the parameters are not part of the function, then if those
declarations are in separate translation units, there's little way to
enforce that this should fail to compile / link.
Any reasons to disallow this? I mean, this is already possible:

void foo(int = 1);

void f() {
void foo(int = 2);
foo();
}

I'm not saying that this is good code, but the truth is that indeed there
is no way to enforce this requirement over multiple TUs for every single
case. There is the possibility of making this IF;NDR, but really, I don't
see why I shouldn't be able to rename parameters (coding/style guidelines?).
Post by Justin Bassett
Now for templates. In order to have higher-order functions which work on
named parameters, I believe it is necessary to have a new kind of template
Oh I don't like this; it's too different if you know what I mean. What do
you think of saying that the named parameter is implicitly part of the
expansion if the expansion happens in a function parameter list?

template <typename ...Ts>
auto f(Ts ...Args) { // No change here.
g(Args...); // Same.
return {Args...}[0]; // Same.
}

f(1, 2); // ok: calls g(1, 2); returns 1
f(.Lhs = 1, .Rhs = 2); // ok; calls g(.Lhs = 1, .Rhs = 2); returns 1

For example, it would be nice to be easily able to specify the allocator of
Post by Justin Bassett
an unordered_map: std::unordered_map<Key, Value, .allocator = MyAllocator> .
I believe this would break ABI compatibility, though.
How would this break ABI compatibility? The name of the function arguments
need to to be mangled (which is a non-issue for templates in any case).
Post by Justin Bassett
I'm working on a paper to write this up more formally, but before I do
that, I wanted to share my research and work and generate some discussion.
Currently, it is possible to pass parameters by position, but not by name.
To work around this limitation, there are a multitude of solutions. A few
- The "Named Parameters Idiom," sometimes called the Builder Pattern.
- Boost Parameters
<https://www.boost.org/doc/libs/1_68_0/libs/parameter/doc/html/index.html>.
Overloads operator= to make it look like a named parameter.
- Boost Graph's named parameters. Parameter values are passed via
member functions.
- Strong types. This suffers from the limitation that parameters
cannot be reordered, and sometimes you'd have to create types that
otherwise have no meaning.
- Designated Initializers. There are those who hope that designated
initializers will work as named parameters, but they don't work that well.
- Hard to maintain.
- Have to prefix every argument with the library's namespace, or else
use a lot of using declarations or even a using directive.
- Each argument has to be passed in order (Strong types), otherwise
it's a ton of overloads for the library author to work out.
- Possibly worse code-gen
I claim we should standardize a way of passing named arguments in C++.
- Named-or-positional parameters.
- Name-only parameters
- Either of the above combined with default arguments
Syntax: there are two possible syntaxes I've seen that work for named
foo(.name = value)
foo(name: value)
I honestly don't care which we go for, but for consistency with designated
initializers (which may be a bad thing if the behavior is significantly
different), I'm going to choose the foo(.name = value) syntax for the
time being.
For declaring a function with named parameters, it is imperative that it
is opt-in, otherwise, functions parameter names become part of the public
int foo(int .x);
It might be tempting to separate the name of the parameter from the name
used in named parameters, but I claim this overly repetitive. As long as
named parameters are opt-in, having to give an alternative name is
completely redundant. (I believe Swift does this)
There should be some way to specify that the parameter is name-only. For
example, altering Python's implementation
// anything after the . is name-only
int foo(., int .x);
Default arguments should be able to work as they are now.
It's a pretty standard rule that all named arguments must come after all
positional arguments. It is also pretty standard that named arguments can
be in a different order than in the function declaration. I don't see a
compelling reason to break from this, even though there are exceptions in
languages today (e.g. C# and Swift)
There are some options on how the named parameters should work. It could work
like C# and just reorder the arguments
<https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/named-and-optional-arguments#overload-resolution>.
However, I believe that the name should be part of the function type and
should be mangled into the name for the function. It should not be allowed
int foo(int .x, int .y);
int foo(int .a, int .b);
If the name of the parameters are not part of the function, then if those
declarations are in separate translation units, there's little way to
enforce that this should fail to compile / link.
This does bring in the issue that it becomes harder to change existing
APIs to accept named parameters in an ABI compatible manner. For this,
maybe the compiler could emit two symbols for the named-positional argument
case? Otherwise, I think there should be some way to either cause the
compiler to emit two symbols or otherwise maintain ABI compatibility.
Now for templates. In order to have higher-order functions which work on
named parameters, I believe it is necessary to have a new kind of template
// I separated the name completely from the type.
// This would severely complicate generic code, however, so maybe there's
// a way to keep both together
template <typename F, .typename Name, typename Arg>
void call(F fn, Arg&& .Name arg) {
// Some syntax to expand the name is needed. I'm not sure what
// a reasonable choice is. There should also probably be a way
// to generate a name from a compile time string.
fn(.(Name) = std::forward<Arg>(arg));
}
template <typename F, .typename Kwarg>
void call(F fn, Kwarg&& arg) {
fn(.(nameof(Kwarg)) = std::forward<Kwarg>(arg));
}
call(sqrt, .x = 9);
call(sqrt, 9); // We didn't enforce name-only in the declaration of call
Reflection could possibly allow us to inspect the actual name supplied
(useful for libraries such as fmt: fmt::format("({x}, {y})", .x = 10, .y
= 20); ), and it would probably be useful to be able to generate a name
from a compile-time string.
How lookup is performed: it's certainly possible to have overloaded
functions along with named parameters. I haven't spent the time yet to
flesh out all the details, but the named parameters can be each in their
own dimension, as compared to the positional dimension.
Further ideas: I don't want to propose this yet, but I would also like to
see named parameters in template parameters. For example, it would be nice
to be easily able to specify the allocator of an unordered_map: std::unordered_map<Key,
Value, .allocator = MyAllocator> . I believe this would break ABI
compatibility, though.
It sounds crazy to add a new kind of template parameter and include the
name of the parameters as part of the function type, but I believe this
would be implementable with some kind of __name<"parameter_name"> type
with some connection to the regular template type, as well as some rules on
reordering (consider something like sorting all name-only parameters
lexicographically and re-mapping named-positional parameters to their
position). I won't know for sure until I attempt an implementation, but I
believe it should work.
References - some things I've found about named parameter design, which I
may have referred to in my writeup above. Most of these I didn't link to
https://www.python.org/dev/peps/pep-3102/
https://internals.rust-lang.org/t/pre-rfc-named-arguments/3831
https://internals.rust-lang.org/t/pre-rfc-named-arguments/3831/196
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/named-and-optional-arguments#overload-resolution
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4172.htm
http://jamboree.github.io/designator-draft.html
https://www.reddit.com/r/cpp/comments/5mdes5/what_happened_to_the_named_parameter_proposal/
--
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
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAPuuy5eBx1ybcPjS6dNsk7n1_c2uhdRBS19qr%3Dq5cj3cTURnLQ%40mail.gmail.com
<https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAPuuy5eBx1ybcPjS6dNsk7n1_c2uhdRBS19qr%3Dq5cj3cTURnLQ%40mail.gmail.com?utm_medium=email&utm_source=footer>
.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CALmDwq05u%2BvxQ2nd%2BoeEhws1s6Ew3Z5ZkSnGoiMh5XXVDKjUMQ%40mail.gmail.com.
Justin Bassett
2018-08-16 06:33:55 UTC
Permalink
Post by Justin Bassett
For declaring a function with named parameters, it is imperative that it
Post by Justin Bassett
is opt-in, otherwise, functions parameter names become part of the public
API of the function, which is undesirable
Pardon my ignorance, but why exactly is this undesirable? Designated
initializer lists are also not opt-in. I don't really see a problem with
this. I can't imagine function parameters to change once they're the
function is part of the API.
Consider all the standard library functions. Suddenly all the parameter
names become public. Here's an example from this reddit thread (
https://www.reddit.com/r/cpp/comments/5mdes5/what_happened_to_the_named_parameter_proposal/
):

std::max(._Left = 1, ._Right = 2)

Those names are not intended to be public. They are named strangely like
this to avoid problems with user defined macros. We *could *standardize
names for every function in the standard, but I believe that is a lot of
work.

Also, that would make parameter names part of the API by default. I believe
library authors would like the opt-in design, as it makes it much easier to
make API compatible changes. Names used as function parameters are not
generally expected to be part of the API. Especially considering that there
is a lot of code already written which assumes that the parameter names are
not part of the API. If we suddenly change it to be part of the API, the
library authors had no say in whether those names should be part of the API.
Post by Justin Bassett
There should be some way to specify that the parameter is name-only. For
Post by Justin Bassett
example, altering Python's implementation
// anything after the . is name-only
int foo(., int .x);
Default arguments should be able to work as they are now.
I disagree with your proposed solution. Name-only parameters naturally
appear when they are after a varadic ("catch-all") parameter, just like in
Python's implementation.
Good point. I don't disagree with this, but I didn't like having to specify
the types for the variadic template pack. Note that PEP 3102, which I
linked to, allows Python to leave off the name for the variadic parameter.
I was imagining something like that
Post by Justin Bassett
template <typename ...T>
void f(T ..., int name);
f(.name = 1); // name-only argument
Now you have a small problem: C's variadic parameters are specified in the
grammar itself to come last, which can be changed but would require some
restructuring. But I don't think it's worth supporting them.
I agree here. If supporting C's varargs is difficult in this case, I don't
consider it a big drawback to disallow them when a function has named
parameters.
Post by Justin Bassett
However, I believe that the name should be part of the function type and
Post by Justin Bassett
should be mangled into the name for the function. It should not be allowed
int foo(int .x, int .y);
int foo(int .a, int .b);
If the name of the parameters are not part of the function, then if those
declarations are in separate translation units, there's little way to
enforce that this should fail to compile / link.
My first reason for doing so was to directly address concerns in a reddit
thread asking about a previous named parameters proposal
<https://www.reddit.com/r/cpp/comments/5mdes5/what_happened_to_the_named_parameter_proposal/>.
I also believe it is wrong for names which are part of the API to be easily
changeable like that. Additionally, consider name-only parameters. If they
could be renamed, that would be dependent on the order in which they are
declared, which I consider to be an implementation detail. I'm okay if it
is allowed, but I strongly prefer it to be disallowed.
Post by Justin Bassett
void foo(int = 1);
void f() {
void foo(int = 2);
foo();
}
Named parameters are very different from default parameters. I dislike that
we can even do this for default arguments. I'd rather be more restrictive
and find we should loosen the restriction later than be less restrictive
and find we should have tightened the restrictions.

I'm not saying that this is good code, but the truth is that indeed there
Post by Justin Bassett
is no way to enforce this requirement over multiple TUs for every single
case. There is the possibility of making this IF;NDR, but really, I don't
see why I shouldn't be able to rename parameters (coding/style guidelines?).
I believe it is possible to enforce this over multiple TUs in some basic
cases, but thinking about it, I guess it is true that it doesn't work for
some of the more complex cases. If we mangle the names of every named
parameter into the symbol, though, that would catch many cases, I believe,
albeit with a not-very-descriptive diagnostic. IF;NDR is my preference
otherwise.
Post by Justin Bassett
Now for templates. In order to have higher-order functions which work on
Post by Justin Bassett
named parameters, I believe it is necessary to have a new kind of template
Oh I don't like this; it's too different if you know what I mean. What do
you think of saying that the named parameter is implicitly part of the
expansion if the expansion happens in a function parameter list?
I thought about this. My primary concern is that functions which were never
designed with named parameters in mind suddenly can be called with named
parameters. I believe it is best to give library authors the chance to
think about this new aspect of the API before opening it up to all named
parameters.

Other things:

- This would be similar to if Python's varargs accepted kwargs as well.
I don't like this.
- How would the library author restrict a function to only named
parameters, or only positional parameters?
- There would be quite a bit of work figuring out all the cases where a
name should be generated and where a name should not be generated. It might
not even be possible.
Post by Justin Bassett
template <typename ...Ts>
auto f(Ts ...Args) { // No change here.
g(Args...); // Same.
return {Args...}[0]; // Same.
}
f(1, 2); // ok: calls g(1, 2); returns 1
f(.Lhs = 1, .Rhs = 2); // ok; calls g(.Lhs = 1, .Rhs = 2); returns 1
For example, it would be nice to be easily able to specify the allocator
Post by Justin Bassett
of an unordered_map: std::unordered_map<Key, Value, .allocator =
MyAllocator> . I believe this would break ABI compatibility, though.
How would this break ABI compatibility? The name of the function arguments
need to to be mangled (which is a non-issue for templates in any case).
It depends on how it is implemented. True, it only has to be a reordering,
in which case it would be fully ABI compatible. For some reason, I was
imagining the names being mangled into the type.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAPuuy5d7ZxTzoV%2BFaXrM0zd-QrDwctDWRPO_t002PQgHvwF07A%40mail.gmail.com.
TONGARI J
2018-08-16 06:54:53 UTC
Permalink
Yeah, I see you linked to my early draft
<http://jamboree.github.io/designator-draft.html>, and it's actually been
extended further to support perfect forwarding of designators.
Well, I didn't write a new version of the draft, however, some idea can be
found in this thread
<https://www.reddit.com/r/cpp/comments/61r0qf/rfc_template_declname_parameter_and/>
.

The "crazy new kind of template parameter" you mentioned is implemented in
my prototype and it's called "template declname parameter".
It's not restricted to named parameters. See the above thread if you're
interested.

I didn't make designator part of the function type, but things got
complicated after the introduction of designating-type (i.e a combination
of type and designator, e.g. "int.a").
The designating-type is a pseudo type, you can't use it to declare a
variable, it's only purpose is for template to decompose it.
Now a function has 2 types - one without designators and one with
designators

Consider the following:

void f(int.a, int.b);

template<class F>
void call1(F f);

template<class R, class... A, declname... N>
void call2(R(*f)(A.N...));

call1(f); // call1 is void(void(*)(int, int))
call2(f); // call2 is void(void(*)(int.a, int.b))

The designated version is only used if you ask for explicitly, so call1
gets the plain-old-function-type, while call2 gets designated-function-type.

There's also an idea I didn't explored but probably nice to have - allowing
the parameters to have 2 names (interface & impl), e.g.

template<class T>
void copy(T.from a, T&.to b) {
b = a;
}
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/274ad6a3-d111-486c-a900-bc5e01da186a%40isocpp.org.
m***@gmail.com
2018-08-16 07:28:49 UTC
Permalink
Note that, because of Python and C# popularity, this has been suggested
multiple times in one for or another. Never passed.

Also you missed some
proposals http://jamboree.github.io/designator-draft.html
and http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0671r0.html

The latter did not pass and is turned into the
poor-mans http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2018/p0671r2.html

In other words, you should state what is different.

I am personally *pro* named arguments, but the chances are (extremely) low.
I have written a post here, just 10 days ago, on a (more or less)
alternative solution
- https://groups.google.com/a/isocpp.org/d/msg/std-proposals/wz0a7NrwnGQ/iBpN8pYMFQAJ

In any case
- C#-like and Python-like solutions have failed already.
- Solutions that modify the signature and/or the typesystem are doomed for
multiple reasons.
Also there are people that find named arguments *completely* unneeded and
such people might as well be in the committee.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/1510edaf-324a-403c-95bd-0f3fb42ba118%40isocpp.org.
Justin Bassett
2018-08-17 04:04:06 UTC
Permalink
Post by m***@gmail.com
Note that, because of Python and C# popularity, this has been suggested
multiple times in one for or another. Never passed.
Also you missed some proposals
http://jamboree.github.io/designator-draft.html
and http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0671r0.html
The latter did not pass and is turned into the poor-mans
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2018/p0671r2.html
In other words, you should state what is different.
I wasn't aware of P0671. My proposal is similar to R0, but more different
from R2. Ignoring syntax differences, P0671r0 makes named parameters opt-in
and only supports name-only parameters. P0671r2 goes in a completely
different direction and makes parameters named by default and
named-positional, with a possible attribute for name-only. P0671 talks
about ellipses, which I haven't investigated yet, but I don't believe I
would stray too far from that. P0671r2 looks like nothing more than
parameter reordering, which I believe to be an inferior form of named
parameters. I didn't see any mention of template functions, but I believe
P0671 only supports named parameters on the outermost layer. My proposal
works to integrate named parameters into the language as a core language
feature rather than as simple syntactic sugar on top.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAPuuy5es%3D3Vfg%3DDrSpy3EPzotL5UOQhbg34vWtQ_y8QZOFx%2B0g%40mail.gmail.com.
David Brown
2018-08-16 11:53:59 UTC
Permalink
Post by Justin Bassett
I'm working on a paper to write this up more formally, but before I do
that, I wanted to share my research and work and generate some discussion.
I am at a loss to why people key wanting to make this such a complicated
issue.

Let's simplify things, and look at the requirements:

1. We want to be able to use named parameters. It leads to clearer code
and fewer errors - especially for functions with several parameters.

2. The primary use is to check that parameters are given in the right
order, with the ability to re-order parameters at the call site as a
secondary concern.

3. It should not require changes to existing code, new ABIs, new object
file formats, or anything more than minimal changes to the compiler
front-end.

We do /not/ want this to be part of a function's signature - there is no
benefit to it, and vast complications involved. In most well-written
code a function (if exported) is declared once in a header somewhere,
and this declaration is available when the function's definition is
seen. So checking for matching parameter names can be done then - just
as checking is done for matching numbers and types. Compilers can warn
on mismatches. And if the declaration and definition are independent,
then it's the programmer's responsibility to make sure they work
together - just as for other aspects of functions.

(I appreciate that there are advantages in allowing names to be part of
the signature - it would let you distinguish "complex(double r, double
i)" and "complex(double r, double theta)". But the added complexity and
implementation effort needed would not be worth it - such costly ideas
hinder the adoption of the main feature. And there would be nothing to
stop this being added in some way at a later date.)


Named parameters are only relevant to function /calls/ - not to function
definitions. The names to use come from a function's declaration - the
argument names in a function's definition are irrelevant (though a
compiler warning to check they match would be a useful implementation
feature). They are very similar, therefore, to default arguments.

int foo(int a, int b, int c = 3, int d = 4);

All these mean the same thing:

foo(1, 2, 3, 4);
foo(1, 2, 3);
foo(.a = 1, .b = 2, .c = 3, .d = 4);
foo(.b = 2, .a = 1, 3);
foo(.d = 4, .b = 2, .a = 1);


These are errors (for obvious reasons):

foo(.ab = 1, 2);
foo(.c = 3, 2, 3);


Within the call parameters, the compiler will take the list of calling
parameters and match it up with a list of parameters in the function
declaration. First, any named parameters are put in the right spot
according to name. Then any unnamed parameters are put in the same spot
number as they had in the call. Any empty spots are filled with the
default values. If any spot has no value, or more than one value, it's
an error.


If a function is declared with some unnamed parameters, and re-declared
with names for some of these parameters, that's fine - the current set
of names is the union of these. If a function is redeclared giving the
same name to parameters, that's fine too. If a function is redeclared
and there is a conflict in a parameter name, or if a parameter is never
given a name, then that parameter can't be used as a named parameter.
An exception would be that parameter names with reserved identifiers are
considered anonymous - you can't match on such a name.

An alternative resolution here would be simply to say that the last seen
declaration is the one that counts in regard to parameter names.
(Again, compiler warnings for conflicts, excluding reserved identifiers,
would be encouraged.)



That is /all/ that is needed. It could be implemented simply (well,
relatively simply!) in any C++ compiler front-end. It does not conflict
with existing syntax, it will not change the meaning of any existing
code. New headers can be written to take advantage of the feature, but
such functions can still be used with positional parameters.

The same feature can also be used for template arguments.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/pl3ogk%24csr%241%40blaine.gmane.org.
m***@gmail.com
2018-08-16 13:08:23 UTC
Permalink
There are tree major problems with such simple approaches

First - you make something, that has been private for 30+ years, public.
Second - warnings are not good enough. There is no situation where wrong
argument is ignorable and not an error. If you make named arguments that
weak, one can just use comments.
Third - perfect forwarding must work.
Post by Justin Bassett
Post by Justin Bassett
I'm working on a paper to write this up more formally, but before I do
that, I wanted to share my research and work and generate some
discussion.
I am at a loss to why people key wanting to make this such a complicated
issue.
1. We want to be able to use named parameters. It leads to clearer code
and fewer errors - especially for functions with several parameters.
2. The primary use is to check that parameters are given in the right
order, with the ability to re-order parameters at the call site as a
secondary concern.
3. It should not require changes to existing code, new ABIs, new object
file formats, or anything more than minimal changes to the compiler
front-end.
We do /not/ want this to be part of a function's signature - there is no
benefit to it, and vast complications involved. In most well-written
code a function (if exported) is declared once in a header somewhere,
and this declaration is available when the function's definition is
seen. So checking for matching parameter names can be done then - just
as checking is done for matching numbers and types. Compilers can warn
on mismatches. And if the declaration and definition are independent,
then it's the programmer's responsibility to make sure they work
together - just as for other aspects of functions.
(I appreciate that there are advantages in allowing names to be part of
the signature - it would let you distinguish "complex(double r, double
i)" and "complex(double r, double theta)". But the added complexity and
implementation effort needed would not be worth it - such costly ideas
hinder the adoption of the main feature. And there would be nothing to
stop this being added in some way at a later date.)
Named parameters are only relevant to function /calls/ - not to function
definitions. The names to use come from a function's declaration - the
argument names in a function's definition are irrelevant (though a
compiler warning to check they match would be a useful implementation
feature). They are very similar, therefore, to default arguments.
int foo(int a, int b, int c = 3, int d = 4);
foo(1, 2, 3, 4);
foo(1, 2, 3);
foo(.a = 1, .b = 2, .c = 3, .d = 4);
foo(.b = 2, .a = 1, 3);
foo(.d = 4, .b = 2, .a = 1);
foo(.ab = 1, 2);
foo(.c = 3, 2, 3);
Within the call parameters, the compiler will take the list of calling
parameters and match it up with a list of parameters in the function
declaration. First, any named parameters are put in the right spot
according to name. Then any unnamed parameters are put in the same spot
number as they had in the call. Any empty spots are filled with the
default values. If any spot has no value, or more than one value, it's
an error.
If a function is declared with some unnamed parameters, and re-declared
with names for some of these parameters, that's fine - the current set
of names is the union of these. If a function is redeclared giving the
same name to parameters, that's fine too. If a function is redeclared
and there is a conflict in a parameter name, or if a parameter is never
given a name, then that parameter can't be used as a named parameter.
An exception would be that parameter names with reserved identifiers are
considered anonymous - you can't match on such a name.
An alternative resolution here would be simply to say that the last seen
declaration is the one that counts in regard to parameter names.
(Again, compiler warnings for conflicts, excluding reserved identifiers,
would be encouraged.)
That is /all/ that is needed. It could be implemented simply (well,
relatively simply!) in any C++ compiler front-end. It does not conflict
with existing syntax, it will not change the meaning of any existing
code. New headers can be written to take advantage of the feature, but
such functions can still be used with positional parameters.
The same feature can also be used for template arguments.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/f3af9e48-f865-476e-8724-4af19ce23369%40isocpp.org.
David Brown
2018-08-17 10:14:15 UTC
Permalink
Post by m***@gmail.com
There are tree major problems with such simple approaches
First - you make something, that has been private for 30+ years, public.
No, it is not. The names for parameters are in function declarations,
in headers - these are public. My proposal does not use names from the
definitions (which may be private).

Some functions are declared without parameter names - you can't use them
for named parameters, without a re-declaration. Some functions are
declared with "private" reserved names as parameter names (especially in
standard library implementations, to avoid conflict with any macros the
user may have defined). By my proposal, you can't use them either as
parameter names.
Post by m***@gmail.com
Second - warnings are not good enough. There is no situation where wrong
argument is ignorable and not an error. If you make named arguments that
weak, one can just use comments.
I'd have no problem with errors rather than warnings.

But I would want to be able to call existing functions using named
arguments, and I would want to call new functions with positional
arguments. I am sceptical to the idea of being able to force the use of
named arguments at any point (in fact, that would, I think, cause more
problems for perfect forwarding), and the whole idea would be useless if
special syntax were needed to declare that a function uses named parameters.
Post by m***@gmail.com
Third - perfect forwarding must work.
Perfect forwarding would work fine, as far as I can see. However, I
don't claim to be particularly familiar with perfect forwarding, and I
would appreciate corrections if it looks like I've got things wrong
here. I agree that perfect forwarding /should/ work - I'm less
convinced that it /must/ work. Again, I am frustrated that a simple
feature that could be extremely useful in many cases is missing merely
because it can't be used in some other cases.


Here is an example:

template<typename T, typename... Args>
unique_ptr<T> make_unique(Args&&... args)
{
return unique_ptr<T>(new T(std::forward<Args>(args)...));
}

And let's make a class:

class Point {
public:
Point(int x, int y, int z);
...
}

This means you can have:

int a = 1;
const int b = 2;

auto p1 = make_unique<Point>(a, b, 3);

When the compiler sees this "make_unique" call, it also has the
declaration of Point's constructor available. So if you write this:

auto p2 = make_unique<Point>(.y = b, .z = 3, .x = a);

the compiler knows the names of the parameters in the constructor, and
can re-arrange them to give exactly the same call as the positional
arguments.

Is this what you were looking for, or did you mean something else?
Post by m***@gmail.com
Post by Justin Bassett
I'm working on a paper to write this up more formally, but before
I do
Post by Justin Bassett
that, I wanted to share my research and work and generate some
discussion.
I am at a loss to why people key wanting to make this such a complicated
issue.
1. We want to be able to use named parameters. It leads to clearer code
and fewer errors - especially for functions with several parameters.
2. The primary use is to check that parameters are given in the right
order, with the ability to re-order parameters at the call site as a
secondary concern.
3. It should not require changes to existing code, new ABIs, new object
file formats, or anything more than minimal changes to the compiler
front-end.
We do /not/ want this to be part of a function's signature - there is no
benefit to it, and vast complications involved. In most well-written
code a function (if exported) is declared once in a header somewhere,
and this declaration is available when the function's definition is
seen. So checking for matching parameter names can be done then - just
as checking is done for matching numbers and types. Compilers can warn
on mismatches. And if the declaration and definition are independent,
then it's the programmer's responsibility to make sure they work
together - just as for other aspects of functions.
(I appreciate that there are advantages in allowing names to be part of
the signature - it would let you distinguish "complex(double r, double
i)" and "complex(double r, double theta)". But the added complexity and
implementation effort needed would not be worth it - such costly ideas
hinder the adoption of the main feature. And there would be nothing to
stop this being added in some way at a later date.)
Named parameters are only relevant to function /calls/ - not to function
definitions. The names to use come from a function's declaration - the
argument names in a function's definition are irrelevant (though a
compiler warning to check they match would be a useful implementation
feature). They are very similar, therefore, to default arguments.
int foo(int a, int b, int c = 3, int d = 4);
foo(1, 2, 3, 4);
foo(1, 2, 3);
foo(.a = 1, .b = 2, .c = 3, .d = 4);
foo(.b = 2, .a = 1, 3);
foo(.d = 4, .b = 2, .a = 1);
foo(.ab = 1, 2);
foo(.c = 3, 2, 3);
Within the call parameters, the compiler will take the list of calling
parameters and match it up with a list of parameters in the function
declaration. First, any named parameters are put in the right spot
according to name. Then any unnamed parameters are put in the same spot
number as they had in the call. Any empty spots are filled with the
default values. If any spot has no value, or more than one value, it's
an error.
If a function is declared with some unnamed parameters, and re-declared
with names for some of these parameters, that's fine - the current set
of names is the union of these. If a function is redeclared giving the
same name to parameters, that's fine too. If a function is redeclared
and there is a conflict in a parameter name, or if a parameter is never
given a name, then that parameter can't be used as a named parameter.
An exception would be that parameter names with reserved identifiers are
considered anonymous - you can't match on such a name.
An alternative resolution here would be simply to say that the last seen
declaration is the one that counts in regard to parameter names.
(Again, compiler warnings for conflicts, excluding reserved identifiers,
would be encouraged.)
That is /all/ that is needed. It could be implemented simply (well,
relatively simply!) in any C++ compiler front-end. It does not conflict
with existing syntax, it will not change the meaning of any existing
code. New headers can be written to take advantage of the feature, but
such functions can still be used with positional parameters.
The same feature can also be used for template arguments.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/pl671k%24gsb%241%40blaine.gmane.org.
Matthew Woehlke
2018-08-17 15:16:17 UTC
Permalink
Post by David Brown
Post by m***@gmail.com
There are tree major problems with such simple approaches
First - you make something, that has been private for 30+ years, public.
No, it is not. The names for parameters are in function declarations,
in headers - these are public.
No, they aren't. Or, more correctly, while they are "public" in the
sense that a user can see them by reading the header, they aren't a
(normative) part of the API, any more than comments are. To *the
compiler*, they may as well not exist.

You are proposing to change that. That is a *serious* change.
Post by David Brown
But I would want to be able to call existing functions using named
arguments, and I would want to call new functions with positional
arguments. I am sceptical to the idea of being able to force the use of
named arguments at any point
I don't think anyone has proposed that, with one exception:

foo(int :a, int :b = 3, int :c = 12);
foo(1, c: 6); // name *must* be used here because 'b' is omitted

At least, I don't know any reason why we would need to require names to
be used, other than the above example.
Post by David Brown
and the whole idea would be useless if
special syntax were needed to declare that a function uses named parameters.
I don't think you can *avoid* that, since there is very strong
opposition (see above) to turning all existing functions into functions
that have named parameters. Also, everyone that *is* proposing to have
named parameters with syntax apparently don't share this opinion.
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/823c098a-0fb0-18c3-82f3-e8a8616312f1%40gmail.com.
Jake Arkinstall
2018-08-17 16:17:56 UTC
Permalink
Post by Matthew Woehlke
foo(int :a, int :b = 3, int :c = 12);
foo(1, c: 6); // name *must* be used here because 'b' is omitted
Ah. That does demolish my idea about using strong types as named wrappers
for the underlying type. Well, it makes it insufficient, at least - in
order to make it work we'd need to change the language to keep trying
parameter ordering until the types fit.

Unlike an approach that changes mangling directly, this does mean that the
following non-named code would become valid:

foo(const int& a=1, const std::string& b="hello");
foo("world"); //yuck

Which, innocent enough in this example, is going to be a source of bugs
when an implicit conversion exists - unless that ordering search matches
act as explicit, which is going to cause its own problems in terms of
usability.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAC%2B0CCP6nzxYMpKXcCMCvi-6wq0XRGs6PZquBQ9Q4t1q_re3AA%40mail.gmail.com.
Matthew Woehlke
2018-08-17 17:00:02 UTC
Permalink
Post by Jake Arkinstall
Post by Matthew Woehlke
foo(int :a, int :b = 3, int :c = 12);
foo(1, c: 6); // name *must* be used here because 'b' is omitted
Ah. That does demolish my idea about using strong types as named wrappers
for the underlying type.
Well... yes and no. "Strong types as named wrappers for the underlying
type" sounds suspiciously like where my own thoughts on this matter have
been going. However, while I would envision a library/type component, we
do *need* language-level support... not just for syntactic sugar, but
for this, specifically. (And since this is my #1 "killer feature" for
named arguments... don't get me wrong, tagged dispatch / named overload
is #2, but skipping arguments is #1 :-).)
Post by Jake Arkinstall
Well, it makes it insufficient, at least - in order to make it work
we'd need to change the language to keep trying parameter ordering
until the types fit.
Unlike an approach that changes mangling directly, this does mean that the
foo(const int& a=1, const std::string& b="hello");
foo("world"); //yuck
Which, innocent enough in this example, is going to be a source of bugs
when an implicit conversion exists - unless that ordering search matches
act as explicit, which is going to cause its own problems in terms of
usability.
I would not allow skipping for unnamed parameters.
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/55d7359d-d249-230d-13c5-0f2f1a4d399b%40gmail.com.
David Brown
2018-08-17 17:12:11 UTC
Permalink
Post by Matthew Woehlke
Post by David Brown
Post by m***@gmail.com
There are tree major problems with such simple approaches
First - you make something, that has been private for 30+ years, public.
No, it is not. The names for parameters are in function declarations,
in headers - these are public.
No, they aren't. Or, more correctly, while they are "public" in the
sense that a user can see them by reading the header, they aren't a
(normative) part of the API, any more than comments are. To *the
compiler*, they may as well not exist.
You are proposing to change that. That is a *serious* change.
Nah, you are overreacting. At most, it is a /tiny/ issue compared to
the huge amount of implementation stuff in typical C++ headers that
really is supposed to be private implementation details. (Hint: lots of
it is labelled "private:".)

It is very common to give sensible names to parameters in headers - just
as it is common to write sensible comments in headers. Yes, the
compiler ignores them - but humans reading the headers do not, and lots
of other tools do /not/ ignore either parameter names or even comments.
IDE's regularly show parameter names in some sort of tooltip or hint
when you are typing a function call, or will show them as a sort of
function summary - possibly along with nearby comments. Documentation
tools like doxygen use them.

If you want to make it hard for people to use functions by obscuring the
point of the parameters, leave them unnamed. Don't put a name in the
header and pretend it's a secret.
Post by Matthew Woehlke
Post by David Brown
But I would want to be able to call existing functions using named
arguments, and I would want to call new functions with positional
arguments. I am sceptical to the idea of being able to force the use of
named arguments at any point
foo(int :a, int :b = 3, int :c = 12);
foo(1, c: 6); // name *must* be used here because 'b' is omitted
At least, I don't know any reason why we would need to require names to
be used, other than the above example.
Some people have suggested a syntax for function declarations (or
definitions) that indicated that one or more of the parameters /must/ be
used as named parameters. I can see that being useful if they are to be
used for overloads, but not otherwise.
Post by Matthew Woehlke
Post by David Brown
and the whole idea would be useless if
special syntax were needed to declare that a function uses named parameters.
I don't think you can *avoid* that, since there is very strong
opposition (see above) to turning all existing functions into functions
that have named parameters. Also, everyone that *is* proposing to have
named parameters with syntax apparently don't share this opinion.
I don't think your argument against allowing people to use named
parameters for existing functions is at all convincing. I am happy to
accept that /you/ have strong opinions against it - and therefore that
there is /some/ opposition to it. Whether a lot of people share your
opinion here or not, I don't know. All we can be sure about for now is
that some people strongly approve of it, some people strongly oppose it.
I guess that's why we have a C++ standards committee, and not a C++
standards dictatorship.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/pl6vh8%24kta%241%40blaine.gmane.org.
Nicol Bolas
2018-08-17 17:30:46 UTC
Permalink
Post by Justin Bassett
Post by Matthew Woehlke
Post by David Brown
Post by m***@gmail.com
There are tree major problems with such simple approaches
First - you make something, that has been private for 30+ years,
public.
Post by Matthew Woehlke
Post by David Brown
No, it is not. The names for parameters are in function declarations,
in headers - these are public.
No, they aren't. Or, more correctly, while they are "public" in the
sense that a user can see them by reading the header, they aren't a
(normative) part of the API, any more than comments are. To *the
compiler*, they may as well not exist.
You are proposing to change that. That is a *serious* change.
Nah, you are overreacting. At most, it is a /tiny/ issue compared to
the huge amount of implementation stuff in typical C++ headers that
really is supposed to be private implementation details. (Hint: lots of
it is labelled "private:".)
"Overreacting"? Show me a standard library implementation that actually
uses the parameter names that the standard library defines. What's more,
standard libraries *cannot* use those parameter names. Why?

Macro defensiveness.

Users can define macros with almost any names. And standard library headers
are *required* to not be affected by such macros. As such, standard library
implementations are required to use the set of names that macros cannot
touch: names that are restricted for the implementation.

So if you can't even rely on the standard library's parameter names, you
would be unable to write cross-platform code that uses those names. And if
you can't even rely on the *standard* library... what *can* you rely on?
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/c2700ce4-bf0d-4176-b7c0-df038241f4a7%40isocpp.org.
Ville Voutilainen
2018-08-17 17:31:42 UTC
Permalink
"Overreacting"? Show me a standard library implementation that actually uses
the parameter names that the standard library defines. What's more, standard
libraries cannot use those parameter names. Why?
Macro defensiveness.
Users can define macros with almost any names. And standard library headers
are required to not be affected by such macros. As such, standard library
implementations are required to use the set of names that macros cannot
touch: names that are restricted for the implementation.
So if you can't even rely on the standard library's parameter names, you
would be unable to write cross-platform code that uses those names. And if
you can't even rely on the standard library... what can you rely on?
This problem ceases to be a problem once modules land.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUZ6K7WW1N73cu-wv9ypHrWhcBMMqjJP-79mYdv%2BtVRqjQ%40mail.gmail.com.
Nicol Bolas
2018-08-17 17:37:34 UTC
Permalink
Post by Justin Bassett
Post by Nicol Bolas
"Overreacting"? Show me a standard library implementation that actually
uses
Post by Nicol Bolas
the parameter names that the standard library defines. What's more,
standard
Post by Nicol Bolas
libraries cannot use those parameter names. Why?
Macro defensiveness.
Users can define macros with almost any names. And standard library
headers
Post by Nicol Bolas
are required to not be affected by such macros. As such, standard
library
Post by Nicol Bolas
implementations are required to use the set of names that macros cannot
touch: names that are restricted for the implementation.
So if you can't even rely on the standard library's parameter names, you
would be unable to write cross-platform code that uses those names. And
if
Post by Nicol Bolas
you can't even rely on the standard library... what can you rely on?
This problem ceases to be a problem once modules land.
And of course, `#include`s of C++ standard library headers are not required
to actually "include" text files (which is why they don't end in `.h`).
They can just be `import` directives under the hood. Or they can include
text files that themselves just import a module.

That bears thinking about. But at the same time, if we go this route, we
effectively enforce standard libraries to use those names for its
parameters. Names become a de-facto part of their interfaces. That will
make it difficult for standard library implementations to compile on both
C++17 and C++20/whatever-has-modules.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/f79149e0-8d3c-49ca-a2f0-5b8dbb171704%40isocpp.org.
Ville Voutilainen
2018-08-17 17:49:16 UTC
Permalink
Post by Nicol Bolas
Post by Ville Voutilainen
Post by Nicol Bolas
So if you can't even rely on the standard library's parameter names, you
would be unable to write cross-platform code that uses those names. And if
you can't even rely on the standard library... what can you rely on?
This problem ceases to be a problem once modules land.
And of course, `#include`s of C++ standard library headers are not required
to actually "include" text files (which is why they don't end in `.h`). They
can just be `import` directives under the hood. Or they can include text
files that themselves just import a module.
That bears thinking about. But at the same time, if we go this route, we
effectively enforce standard libraries to use those names for its
parameters. Names become a de-facto part of their interfaces. That will make
it difficult for standard library implementations to compile on both C++17
and C++20/whatever-has-modules.
It's worth noting that some languages like Common Lisp do standardize
the names of some
parameters of the standard library functions. So it's not
unfathomable; prior to modules,
the problem was that we _couldn't_ standardize the names, it was just
not possible.

What I have established, having had discussions about named arguments
on multiple occasions,
is that the following pain points are important:

1) it needs to be an opt-in for the author of a library, so no
automagic naming. Some library
authors do not want users relying on names that the library author
didn't expect them to rely
on, in order to avoid breakage that wasn't considered beforehand.

2) The standard library part is the other major one; it's a bit
embarrassing if the facility can't work
with any standard library functions, and prior to modules, it indeed can't.

There have been various suggestions to make names part of the ABI and
part of the function type,
so that the function can't be called without named arguments, in the
traditional ordered-unnamed
arguments.
That makes wrapping such functions in binds and lambdas and whatnot
horrible. Lisp, for example,
still allows ordered-unnamed calls even if some parameters are
declared &key. Making it part
of the ABI is likewise nice for some things (changing the names breaks
ABI, silent change of
meaning doesn't happen for users), but it's unfortunate from other
perspectives, like having
to invent new manglings and again running into problems with
ordered-unnamed calls.

I do expect further discussion and proposals for named arguments. Some
committee members
are trying fairly hard to get named arguments in.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUapCo9kdS2QAyJ%3DjvPFXkbZCTrU9j94ck64RnkS2_Co4A%40mail.gmail.com.
m***@gmail.com
2018-08-17 18:41:10 UTC
Permalink
Post by David Brown
Post by Nicol Bolas
Post by Ville Voutilainen
Post by Nicol Bolas
So if you can't even rely on the standard library's parameter names,
you
Post by Nicol Bolas
Post by Ville Voutilainen
Post by Nicol Bolas
would be unable to write cross-platform code that uses those names.
And
Post by Nicol Bolas
Post by Ville Voutilainen
Post by Nicol Bolas
if
you can't even rely on the standard library... what can you rely on?
This problem ceases to be a problem once modules land.
And of course, `#include`s of C++ standard library headers are not
required
Post by Nicol Bolas
to actually "include" text files (which is why they don't end in `.h`).
They
Post by Nicol Bolas
can just be `import` directives under the hood. Or they can include text
files that themselves just import a module.
That bears thinking about. But at the same time, if we go this route, we
effectively enforce standard libraries to use those names for its
parameters. Names become a de-facto part of their interfaces. That will
make
Post by Nicol Bolas
it difficult for standard library implementations to compile on both
C++17
Post by Nicol Bolas
and C++20/whatever-has-modules.
It's worth noting that some languages like Common Lisp do standardize
the names of some
parameters of the standard library functions. So it's not
unfathomable; prior to modules,
the problem was that we _couldn't_ standardize the names, it was just
not possible.
What I have established, having had discussions about named arguments
on multiple occasions,
1) it needs to be an opt-in for the author of a library, so no
automagic naming. Some library
authors do not want users relying on names that the library author
didn't expect them to rely
on, in order to avoid breakage that wasn't considered beforehand.
2) The standard library part is the other major one; it's a bit
embarrassing if the facility can't work
with any standard library functions, and prior to modules, it indeed can't.
Wouldn't the interface to a template still be its header? Aren't modules
only for compiled code?

How is the relation b/w modules and templates envisioned to be?
Post by David Brown
There have been various suggestions to make names part of the ABI and
part of the function type,
so that the function can't be called without named arguments, in the
traditional ordered-unnamed
arguments.
That makes wrapping such functions in binds and lambdas and whatnot
horrible. Lisp, for example,
still allows ordered-unnamed calls even if some parameters are
declared &key. Making it part
of the ABI is likewise nice for some things (changing the names breaks
ABI, silent change of
meaning doesn't happen for users), but it's unfortunate from other
perspectives, like having
to invent new manglings and again running into problems with
ordered-unnamed calls.
I do expect further discussion and proposals for named arguments. Some
committee members
are trying fairly hard to get named arguments in.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/90ff5e5b-c75a-401c-8179-510b35c95595%40isocpp.org.
Ville Voutilainen
2018-08-17 19:21:25 UTC
Permalink
Post by m***@gmail.com
Wouldn't the interface to a template still be its header? Aren't modules
only for compiled code?
What "header"? You can put templates into a module just fine.
Post by m***@gmail.com
How is the relation b/w modules and templates envisioned to be?
It would need to behave so that the names of parameters are handled in
the context
of the declaration site, not at the context of the instantiation site.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUb_iJ8B%3DELuJgBVo-R3fvPPOcgjMobr_4hvEQSR2%3DoALQ%40mail.gmail.com.
Justin Bassett
2018-08-18 03:37:04 UTC
Permalink
What I've gathered from this discussion is that we want the simplest form
of named parameters that can make it into the standard while not
prohibiting a future proposal for some of the more niche features. After
deliberating on this, I arrived at something quite similar to P0671R0
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0671r0.html> .
Thus, the most important question that needs answering is: what were the
committee's concerns about P0671R0? What were the reasons behind the
changes made in R1 and R2? If we cannot address the concerns the committee
had, there's no reason to propose a similar proposal. Without knowing the
concerns, it's impossible to address them.

On Fri, Aug 17, 2018 at 12:21 PM Ville Voutilainen <
Post by Ville Voutilainen
Post by m***@gmail.com
Wouldn't the interface to a template still be its header? Aren't modules
only for compiled code?
What "header"? You can put templates into a module just fine.
Post by m***@gmail.com
How is the relation b/w modules and templates envisioned to be?
It would need to behave so that the names of parameters are handled in
the context
of the declaration site, not at the context of the instantiation site.
--
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
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUb_iJ8B%3DELuJgBVo-R3fvPPOcgjMobr_4hvEQSR2%3DoALQ%40mail.gmail.com
.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAPuuy5e0XtkLHZ3pX_xkXf1hj-EGzMUM2DQjfRtydKYt4SF5gg%40mail.gmail.com.
m***@gmail.com
2018-08-18 09:26:57 UTC
Permalink
Post by Justin Bassett
What I've gathered from this discussion is that we want the simplest form
of named parameters that can make it into the standard while not
prohibiting a future proposal for some of the more niche features. After
deliberating on this, I arrived at something quite similar to P0671R0
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0671r0.html> .
Thus, the most important question that needs answering is: what were the
committee's concerns about P0671R0? What were the reasons behind the
changes made in R1 and R2? If we cannot address the concerns the committee
had, there's no reason to propose a similar proposal. Without knowing the
concerns, it's impossible to address them.
Here it is -> "introduce a new kind of functions". *That is the reason. *

Also, this obviously does not address the named arguments, that are
optional, the "weak" ones, so this solution will not make everyone happy.


The only solution that covers all use cases is the one that has both types,*
much like* Objective C (strong only) moved to Swift (strong, but some can
be *marked* optional).

We can argue about the syntax or if the name can be different from the
argument, but we should accept, one-sided solution will not work:
- Strong-only will be infuriating and *hated* for every argument named,
that is *not* used for overload disambiguation, even now I hate Objective
C/Swift error:error calls, and for *many, many people *
it is *not* what they expect.
- Weak-only will be seen as "unneeded" by some and*, *in the same time,
not doing their "primary" job - to disambiguate.

We *could* probably introduce these in stages, though, as it is inevitable
to have a "different syntax", much like swift has to have "different
syntax" to mark ignorable ones.
Post by Justin Bassett
Post by Ville Voutilainen
Post by m***@gmail.com
Wouldn't the interface to a template still be its header? Aren't modules
only for compiled code?
What "header"? You can put templates into a module just fine.
Post by m***@gmail.com
How is the relation b/w modules and templates envisioned to be?
It would need to behave so that the names of parameters are handled in
the context
of the declaration site, not at the context of the instantiation site.
--
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
To view this discussion on the web visit
https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUb_iJ8B%3DELuJgBVo-R3fvPPOcgjMobr_4hvEQSR2%3DoALQ%40mail.gmail.com
.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/02b476cc-6a79-46a3-9721-59fcb57b6817%40isocpp.org.
Ville Voutilainen
2018-08-18 11:05:10 UTC
Permalink
What I've gathered from this discussion is that we want the simplest form of
named parameters that can make it into the standard while not prohibiting a
future proposal for some of the more niche features. After deliberating on
this, I arrived at something quite similar to P0671R0 . Thus, the most
important question that needs answering is: what were the committee's
concerns about P0671R0? What were the reasons behind the changes made in R1
and R2? If we cannot address the concerns the committee had, there's no
reason to propose a similar proposal. Without knowing the concerns, it's
impossible to address them.
That proposal hasn't been discussed yet.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUagX8xeYVpVuinLO%2BjmwpqaD%3DOo-ztOLYp_sCCR-wYUyw%40mail.gmail.com.
m***@gmail.com
2018-08-18 11:31:33 UTC
Permalink
Post by Zhihao Yuan
Post by Justin Bassett
What I've gathered from this discussion is that we want the simplest
form of
Post by Justin Bassett
named parameters that can make it into the standard while not
prohibiting a
Post by Justin Bassett
future proposal for some of the more niche features. After deliberating
on
Post by Justin Bassett
this, I arrived at something quite similar to P0671R0 . Thus, the most
important question that needs answering is: what were the committee's
concerns about P0671R0? What were the reasons behind the changes made in
R1
Post by Justin Bassett
and R2? If we cannot address the concerns the committee had, there's no
reason to propose a similar proposal. Without knowing the concerns, it's
impossible to address them.
That proposal hasn't been discussed yet.
Do you mean the later iterations? Because the original was discouraged, according
to the trip report.
<https://blogs.msdn.microsoft.com/vcblog/2017/07/28/trip-report-evolution-working-group-at-the-summer-iso-c-standards-meeting-toronto/>
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/0d5717b4-3009-4b15-850f-e90a53daf230%40isocpp.org.
Ville Voutilainen
2018-08-18 11:55:46 UTC
Permalink
Post by m***@gmail.com
Post by Ville Voutilainen
What I've gathered from this discussion is that we want the simplest form of
named parameters that can make it into the standard while not prohibiting a
future proposal for some of the more niche features. After deliberating on
this, I arrived at something quite similar to P0671R0 . Thus, the most
important question that needs answering is: what were the committee's
concerns about P0671R0? What were the reasons behind the changes made in R1
and R2? If we cannot address the concerns the committee had, there's no
reason to propose a similar proposal. Without knowing the concerns, it's
impossible to address them.
That proposal hasn't been discussed yet.
Do you mean the later iterations? Because the original was discouraged,
according to the trip report.
The R2 version is a different approach. In its preamble, it says
"This is different and I appreciate that you make up your mind based
on what's written here. I am almost certain: you haven't seen this
before."
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUYoyLjs%3DECWjxB9gUMFKYD_z6oMj54DfOE%3DTvNHtZgh1Q%40mail.gmail.com.
m***@gmail.com
2018-08-18 12:06:48 UTC
Permalink
Post by Justin Bassett
On Saturday, August 18, 2018 at 2:05:13 PM UTC+3, Ville Voutilainen
Post by Ville Voutilainen
What I've gathered from this discussion is that we want the simplest form of
named parameters that can make it into the standard while not prohibiting a
future proposal for some of the more niche features. After
deliberating
Post by Ville Voutilainen
on
this, I arrived at something quite similar to P0671R0 . Thus, the
most
Post by Ville Voutilainen
important question that needs answering is: what were the committee's
concerns about P0671R0? What were the reasons behind the changes made
in
Post by Ville Voutilainen
R1
and R2? If we cannot address the concerns the committee had, there's
no
Post by Ville Voutilainen
reason to propose a similar proposal. Without knowing the concerns,
it's
Post by Ville Voutilainen
impossible to address them.
That proposal hasn't been discussed yet.
Do you mean the later iterations? Because the original was discouraged,
according to the trip report.
The R2 version is a different approach. In its preamble, it says
"This is different and I appreciate that you make up your mind based
on what's written here. I am almost certain: you haven't seen this
before."
Yeah, but the Basett was asking about the original, because his idea is the
same as R0
and he wanted to know what made the committee reject it.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/99e4e07a-d2e2-4d0c-963c-d63fba1362a1%40isocpp.org.
Ville Voutilainen
2018-08-18 12:15:11 UTC
Permalink
Post by m***@gmail.com
Post by Ville Voutilainen
Post by m***@gmail.com
Post by Ville Voutilainen
That proposal hasn't been discussed yet.
Do you mean the later iterations? Because the original was discouraged,
according to the trip report.
The R2 version is a different approach. In its preamble, it says
"This is different and I appreciate that you make up your mind based
on what's written here. I am almost certain: you haven't seen this
before."
Yeah, but the Basett was asking about the original, because his idea is the
same as R0
and he wanted to know what made the committee reject it.
I stand corrected. So, looking at the discussion, the R0 version was
so that you couldn't call the functions as usual, with
ordered-unnamed,
and it suggested that the names need to be baked into the ABI. But
even with that removed,
the proposal still didn't pass. There were suggestions that a "fluent
API" (aka a parameter
type that has separate setters for different arguments) should just be
used instead (to which
I commented that that approach was invented 30 years ago and users
refuse to use it). A parameter
struct and use of designated initializers was suggested as another
work-around. Based on the
discussion notes, it seems that Evolution was still unconvinced that
this language feature
is necessary, given the work-arounds. That has been the fate of almost
every one of such
proposals.

If someone wants to work on this, contact Axel. I summarized the
situation at the end of the discussion
on P0671R0 with "Proposals on this will come back. We will not be able
to kill the desire. "
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUYS-ecConWihHFNt-58%2B-_1nHwQVq079q6vtzMWuhYELQ%40mail.gmail.com.
m***@gmail.com
2018-08-18 14:54:39 UTC
Permalink
Post by m***@gmail.com
Post by m***@gmail.com
Post by Ville Voutilainen
Post by m***@gmail.com
Post by Ville Voutilainen
That proposal hasn't been discussed yet.
Do you mean the later iterations? Because the original was
discouraged,
Post by m***@gmail.com
Post by Ville Voutilainen
Post by m***@gmail.com
according to the trip report.
The R2 version is a different approach. In its preamble, it says
"This is different and I appreciate that you make up your mind based
on what's written here. I am almost certain: you haven't seen this
before."
Yeah, but the Basett was asking about the original, because his idea is
the
Post by m***@gmail.com
same as R0
and he wanted to know what made the committee reject it.
I stand corrected. So, looking at the discussion, the R0 version was
so that you couldn't call the functions as usual, with
ordered-unnamed,
and it suggested that the names need to be baked into the ABI. But
even with that removed,
the proposal still didn't pass. There were suggestions that a "fluent
API" (aka a parameter
type that has separate setters for different arguments) should just be
used instead (to which
I commented that that approach was invented 30 years ago and users
refuse to use it). A parameter
struct and use of designated initializers was suggested as another
work-around. Based on the
discussion notes, it seems that Evolution was still unconvinced that
this language feature
is necessary, given the work-arounds. That has been the fate of almost
every one of such
proposals.
Last few days made it clear where the problem is - there is no such thing
like "named arguments" as self-explanatory topic.
Different people expect both different semantics and different
implementations.

This creates noise, and murks the goal - what is the problem need fixing.

If the community stands behind somethings and says:
"This is a problem, we know the workarounds, but they don't work for us
here and here, because this and this, we *really* like this to be improved."
Then the committee will know, they are *fixing* something, *improving* the
language, not just adding a gimmick.

This also goes for the proposals, they should really talk fixing problems
and where workarounds fall short.
Post by m***@gmail.com
If someone wants to work on this, contact Axel. I summarized the
situation at the end of the discussion
on P0671R0 with "Proposals on this will come back. We will not be able
to kill the desire. "
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/99e6dfb8-7331-483d-afeb-e6ae5078c9de%40isocpp.org.
Matthew Woehlke
2018-08-17 17:53:11 UTC
Permalink
Post by David Brown
Post by Matthew Woehlke
Post by David Brown
Post by m***@gmail.com
First - you make something, that has been private for 30+ years, public.
No, it is not. The names for parameters are in function declarations,
in headers - these are public.
No, they aren't. Or, more correctly, while they are "public" in the
sense that a user can see them by reading the header, they aren't a
(normative) part of the API, any more than comments are. To *the
compiler*, they may as well not exist.
You are proposing to change that. That is a *serious* change.
Nah, you are overreacting.
You are certainly entitled to believe that. I happen to disagree, but
more importantly, AFAICT quite a few others also disagree. The point is,
you are facing an uphill battle to convince the committee on this matter.

Right now, changing the names of function parameters is SC+BC. IIUC, you
are proposing to make it at least SIC, if not also BIC. I honestly can't
see how you're going to convince the committee that that's okay.
Post by David Brown
At most, it is a /tiny/ issue compared to
the huge amount of implementation stuff in typical C++ headers that
really is supposed to be private implementation details. (Hint: lots of
it is labelled "private:".)
You mean like this?

class foo
{
...interface...
private:
FooPrivate* d;
};

No so much "leaked" there...
Post by David Brown
Some people have suggested a syntax for function declarations (or
definitions) that indicated that one or more of the parameters /must/ be
used as named parameters. I can see that being useful if they are to be
used for overloads, but not otherwise.
Well, I don't believe I've ever been one of them. I currently don't see
any reason why such a feature would be desirable.

There *are* instances (overload resolution, skipping parameters) when a
*call* needs to use a name, but I don't see the value in having a
declaration that says you *must always* use the name.
Post by David Brown
Post by Matthew Woehlke
Post by David Brown
and the whole idea would be useless if
special syntax were needed to declare that a function uses named parameters.
I don't think you can *avoid* that, since there is very strong
opposition (see above) to turning all existing functions into functions
that have named parameters. Also, everyone that *is* proposing to have
named parameters with syntax apparently don't share this opinion.
I don't think your argument against allowing people to use named
parameters for existing functions is at all convincing.
Who's arguing that?

I would make this perfectly legal:

void foo(int x); // note: not a named parameter
foo(.x=5); // okay, but maybe warn in pedantic mode
foo(.a=5); // okay, but probably warn
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/2755b639-002d-a94b-a3d4-3a0197259cda%40gmail.com.
David Brown
2018-08-17 18:42:17 UTC
Permalink
Post by Matthew Woehlke
Post by David Brown
Post by Matthew Woehlke
Post by David Brown
Post by m***@gmail.com
First - you make something, that has been private for 30+ years, public.
No, it is not. The names for parameters are in function declarations,
in headers - these are public.
No, they aren't. Or, more correctly, while they are "public" in the
sense that a user can see them by reading the header, they aren't a
(normative) part of the API, any more than comments are. To *the
compiler*, they may as well not exist.
You are proposing to change that. That is a *serious* change.
Nah, you are overreacting.
You are certainly entitled to believe that. I happen to disagree, but
more importantly, AFAICT quite a few others also disagree. The point is,
you are facing an uphill battle to convince the committee on this matter.
Fair enough. As I say, I feel differently - but final decisions here
will be up to the committee. I doubt if anything I might say here is
new to the committee - if they didn't like it before, they won't like it
now and I will not be able to convince them. I see C++ from my little
corner of the world, looking at what makes sense to me - they look at a
far, far wider view. They might not make the decision that I think is
best for /me/, but I'm sure they will make a considered judgement on
what they think is best overall.

And certainly if the choice is between named parameters for functions
declared specifically to allow named parameters, or no named parameters
at all, my vote would be with them. A second-best solution would be
better than no solution. (But see my final comment in this post - it
could be that I have been misunderstanding your point.)
Post by Matthew Woehlke
Right now, changing the names of function parameters is SC+BC. IIUC, you
are proposing to make it at least SIC, if not also BIC. I honestly can't
see how you're going to convince the committee that that's okay.
I'm sorry, I don't recognise the abbreviations SC, BC, SIC and BIC.
Post by Matthew Woehlke
Post by David Brown
At most, it is a /tiny/ issue compared to
the huge amount of implementation stuff in typical C++ headers that
really is supposed to be private implementation details. (Hint: lots of
it is labelled "private:".)
You mean like this?
class foo
{
...interface...
FooPrivate* d;
};
No so much "leaked" there...
Well, no, not in a case like this. But when the private section holds
members and possibly inline implementations, it is leaked. This is
especially true of template libraries.
Post by Matthew Woehlke
Post by David Brown
Some people have suggested a syntax for function declarations (or
definitions) that indicated that one or more of the parameters /must/ be
used as named parameters. I can see that being useful if they are to be
used for overloads, but not otherwise.
Well, I don't believe I've ever been one of them. I currently don't see
any reason why such a feature would be desirable.
There *are* instances (overload resolution, skipping parameters) when a
*call* needs to use a name, but I don't see the value in having a
declaration that says you *must always* use the name.
Agreed.
Post by Matthew Woehlke
Post by David Brown
Post by Matthew Woehlke
Post by David Brown
and the whole idea would be useless if
special syntax were needed to declare that a function uses named parameters.
I don't think you can *avoid* that, since there is very strong
opposition (see above) to turning all existing functions into functions
that have named parameters. Also, everyone that *is* proposing to have
named parameters with syntax apparently don't share this opinion.
I don't think your argument against allowing people to use named
parameters for existing functions is at all convincing.
Who's arguing that?
void foo(int x); // note: not a named parameter
foo(.x=5); // okay, but maybe warn in pedantic mode
foo(.a=5); // okay, but probably warn
Do you mean you would be happy to allow the parameter name in an
existing declaration to be used in function calls as a check? But you
would presumably not allow such names to be used for overloads - that
would require a specific extra syntax in the declaration. Is that correct?

I would be entirely happy with such a situation - my main objective is
to aid in writing correct and readable code, and my compiler (given
appropriate flags) would accept "foo(.x = 5)" without complaint while
warning about "foo(.a = 5)", I'd be very satisfied.

I'd been even happier if it accepted this:

void foo(int x, int y);
foo(.y = 1, .x = 2); // Same as foo(2, 1)

But if that's a problem, I'd be fine without it.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/1585ccdc-7057-d8df-a31b-cf9f7de9a6dd%40westcontrol.com.
Matthew Woehlke
2018-08-17 19:11:46 UTC
Permalink
Post by David Brown
Post by Matthew Woehlke
Right now, changing the names of function parameters is SC+BC. IIUC, you
are proposing to make it at least SIC, if not also BIC. I honestly can't
see how you're going to convince the committee that that's okay.
I'm sorry, I don't recognise the abbreviations SC, BC, SIC and BIC.
S/B = source (API) / binary (ABI)
C/IC = [in]compatible

IOW, right now if I release a new version of my library that changes a
parameter name, it has no effect. Under your proposal... does my
previously compiled application (which uses said library) still run
(BC)? Can I recompile it without needing to change its sources (SC)?
Post by David Brown
Post by Matthew Woehlke
   class foo
   {
     ...interface...
     FooPrivate* d;
   };
No so much "leaked" there...
Well, no, not in a case like this.  But when the private section holds
members and possibly inline implementations, it is leaked.  This is
especially true of template libraries.
True. The point is that "some libraries are designed poorly" is not an
excuse to leak even *more*.
Post by David Brown
Post by Matthew Woehlke
Post by David Brown
I don't think your argument against allowing people to use named
parameters for existing functions is at all convincing.
Who's arguing that?
   void foo(int x); // note: not a named parameter
   foo(.x=5); // okay, but maybe warn in pedantic mode
   foo(.a=5); // okay, but probably warn
Do you mean you would be happy to allow the parameter name in an
existing declaration to be used in function calls as a check?
If I make a call with a named parameter that resolves to a function that
does not have explicitly named parameters, then yes, I'm fine with the
compiler *warning* me if the names don't match.
Post by David Brown
But you would presumably not allow such names to be used for
overloads - that would require a specific extra syntax in the
declaration. Is that correct?
Right.

I guess in that sense what I'm proposing is opt-out weak naming (that
only involves a possible compiler warning if you mismatch names) with
opt-in strong naming, where the "fun stuff" (argument skipping, and per
your question, name-based overloading) requires 'strong' naming.

The only way to opt out would be by not naming your parameters *at all*.
However, I guess if you wrote:

void foo(int x, int y);
void foo(int a, int b);

...then *either* `foo(.a=1)` or `foo(.x=1)` should be accepted with no
warning, and would call the same function. But this is all QoI stuff
that doesn't need to be part of the standard.
Post by David Brown
I would be entirely happy with such a situation - my main objective is
to aid in writing correct and readable code, and my compiler (given
appropriate flags) would accept "foo(.x = 5)" without complaint while
warning about "foo(.a = 5)", I'd be very satisfied.
    void foo(int x, int y);
    foo(.y = 1, .x = 2);    // Same as foo(2, 1)
But if that's a problem, I'd be fine without it.
Well, it would *accept* that... with a warning... but it would be the
same as `foo(1, 2)` :-). If you wrote instead:

void foo(int .x, int .y);

...then it would either do what you meant, or be a hard error. I'm on
the fence whether reordering should be allowed. (And by "on the fence" I
mean a) *I* don't feel strongly either way, and b) I think there are
strong arguments for either case.)
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/54e34f7c-f32b-a912-5229-240f855c9fad%40gmail.com.
David Brown
2018-08-19 11:23:00 UTC
Permalink
Post by Matthew Woehlke
Post by David Brown
Post by Matthew Woehlke
Right now, changing the names of function parameters is SC+BC. IIUC, you
are proposing to make it at least SIC, if not also BIC. I honestly can't
see how you're going to convince the committee that that's okay.
I'm sorry, I don't recognise the abbreviations SC, BC, SIC and BIC.
S/B = source (API) / binary (ABI)
C/IC = [in]compatible
IOW, right now if I release a new version of my library that changes a
parameter name, it has no effect. Under your proposal... does my
previously compiled application (which uses said library) still run
(BC)? Can I recompile it without needing to change its sources (SC)?
Let's skip the name parameter overloading bit for now. That is a new
feature, which would let you do something you could not do before, and
requires multiple changes (in compilers, and in source code that uses
it) to support. I have given a suggestion of how it could be
implemented, because it is a feature some people want - I am not
personally convinced that it is an important feature to have, and
certainly not convinced it is worth the price in therms of changes. So
here I am talking about the optional use of parameter names to improve
readability, help write correct code, help spot incorrect code, and -
optionally - to allow re-arranging of parameter order and skipping
defaults using names.

First, if you don't /use/ named parameters, then nothing (binary or
source) changes. That is important to my proposal.

A library generally consists of four parts - documentation, headers to
allow code to use the library, source of the implementation, and
binaries of the implementation. A release to others will have the first
two parts and one or both of the second two parts.

For code that uses the library, if they want to use named parameters
then the libraries headers need to be consistent about parameter names.
If the library documentation says that's okay, and considers the
parameter names to be part of the stable interface for the libraries,
then user could can use the names straight away - no library changes are
needed. (It is not uncommon for library documentation to be wholly or
partly generated automatically by tools like doxygen, which do view
parameter names as significant.) If the documentation does not say so,
then the user is taking a risk or tying their code to a specific library
release.

If you as the library implementer want to change a parameter name in the
headers, that's fair enough if you didn't say they would be consistent,
and a breaking change if you did - just like countless other kinds of
changes to a library API. If you want to change the parameter names
inside the implementation code, that's also fine. It would generally be
a bad idea to have them inconsistent with the headers, but it is
certainly allowable - the compiler would accept them, with optional
warnings.

I can't see how you would be any source or binary incompatibilities that
are not basically the same as you get with relying on any other kind of
implementation details that are not guaranteed to be fixed.
Post by Matthew Woehlke
Post by David Brown
Post by Matthew Woehlke
   class foo
   {
     ...interface...
     FooPrivate* d;
   };
No so much "leaked" there...
Well, no, not in a case like this.  But when the private section holds
members and possibly inline implementations, it is leaked.  This is
especially true of template libraries.
True. The point is that "some libraries are designed poorly" is not an
excuse to leak even *more*.
The use of PIMPLE is /not/ a black-or-white mark of good library design!

And the use of named parameters from the public header information does
not involve /any/ leak that was not already leaked from before.
Post by Matthew Woehlke
Post by David Brown
Post by Matthew Woehlke
Post by David Brown
I don't think your argument against allowing people to use named
parameters for existing functions is at all convincing.
Who's arguing that?
   void foo(int x); // note: not a named parameter
   foo(.x=5); // okay, but maybe warn in pedantic mode
   foo(.a=5); // okay, but probably warn
Do you mean you would be happy to allow the parameter name in an
existing declaration to be used in function calls as a check?
If I make a call with a named parameter that resolves to a function that
does not have explicitly named parameters, then yes, I'm fine with the
compiler *warning* me if the names don't match.
I agree.
Post by Matthew Woehlke
Post by David Brown
But you would presumably not allow such names to be used for
overloads - that would require a specific extra syntax in the
declaration. Is that correct?
Right.
Good.
Post by Matthew Woehlke
I guess in that sense what I'm proposing is opt-out weak naming (that
only involves a possible compiler warning if you mismatch names) with
opt-in strong naming, where the "fun stuff" (argument skipping, and per
your question, name-based overloading) requires 'strong' naming.
Certainly I fully agree that name-based overloading requires "strong"
naming - where the declaration has a new syntax saying that names /must/
be used in some form, and where the parameter names become part of the
ABI for the function. (I hope that could be achieved with name
mangling, or with types somehow, in order to minimise the implementation
changes needed.)

I also think that common use, checked with optional compiler warnings
(which could of course be errors if you choose appropriate compiler
flags), can be done with "weak" naming - using parameter names declared
as they are today in existing code.

I'd perhaps prefer somewhat strong warnings or errors - using parameter
names in a call when the declaration had no names could be an optional
warning, but using parameter names incorrectly when the declaration has
names should likely be an error by default.

There are two other use-cases where there could be debate about the best
solution:

If the call has the right parameter names, but the wrong order, should
that be a warning, or error, or should the compiler "magically" correct
the order? If strong naming is used, the compiler should certainly be
able to re-order the parameters without giving any complaints. But with
weak naming, opinions are going to be more varied. I would like the
compiler to do the re-ordering, but I would be okay with an error
message - this would probably be the simplest and least risky solution.

The other case is for skipping arguments. Again, with strong naming
this should be supported. I believe it /could/ be supported fine with
weak naming, but would again be okay with the safer solution of not
allowing it without strong naming.
Post by Matthew Woehlke
The only way to opt out would be by not naming your parameters *at all*.
void foo(int x, int y);
void foo(int a, int b);
...then *either* `foo(.a=1)` or `foo(.x=1)` should be accepted with no
warning, and would call the same function. But this is all QoI stuff
that doesn't need to be part of the standard.
Post by David Brown
I would be entirely happy with such a situation - my main objective is
to aid in writing correct and readable code, and my compiler (given
appropriate flags) would accept "foo(.x = 5)" without complaint while
warning about "foo(.a = 5)", I'd be very satisfied.
    void foo(int x, int y);
    foo(.y = 1, .x = 2);    // Same as foo(2, 1)
But if that's a problem, I'd be fine without it.
Well, it would *accept* that... with a warning... but it would be the
void foo(int .x, int .y);
...then it would either do what you meant, or be a hard error. I'm on
the fence whether reordering should be allowed. (And by "on the fence" I
mean a) *I* don't feel strongly either way, and b) I think there are
strong arguments for either case.)
That all seems fine to me. (I'm on the side that would /like/
reordering, but not far enough to feel it is a requirement. And I agree
about there being arguments both ways.)
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/5dde96f3-24bc-0499-8019-eb8195bdaded%40westcontrol.com.
m***@gmail.com
2018-08-19 12:52:01 UTC
Permalink
Post by David Brown
Post by Matthew Woehlke
Post by David Brown
Post by Matthew Woehlke
Right now, changing the names of function parameters is SC+BC. IIUC,
you
Post by Matthew Woehlke
Post by David Brown
Post by Matthew Woehlke
are proposing to make it at least SIC, if not also BIC. I honestly
can't
Post by Matthew Woehlke
Post by David Brown
Post by Matthew Woehlke
see how you're going to convince the committee that that's okay.
I'm sorry, I don't recognise the abbreviations SC, BC, SIC and BIC.
S/B = source (API) / binary (ABI)
C/IC = [in]compatible
IOW, right now if I release a new version of my library that changes a
parameter name, it has no effect. Under your proposal... does my
previously compiled application (which uses said library) still run
(BC)? Can I recompile it without needing to change its sources (SC)?
Let's skip the name parameter overloading bit for now. That is a new
feature, which would let you do something you could not do before, and
requires multiple changes (in compilers, and in source code that uses
it) to support. I have given a suggestion of how it could be
implemented, because it is a feature some people want - I am not
personally convinced that it is an important feature to have, and
certainly not convinced it is worth the price in therms of changes. So
here I am talking about the optional use of parameter names to improve
readability, help write correct code, help spot incorrect code, and -
optionally - to allow re-arranging of parameter order and skipping
defaults using names.
First, if you don't /use/ named parameters, then nothing (binary or
source) changes. That is important to my proposal.
A library generally consists of four parts - documentation, headers to
allow code to use the library, source of the implementation, and
binaries of the implementation. A release to others will have the first
two parts and one or both of the second two parts.
For code that uses the library, if they want to use named parameters
then the libraries headers need to be consistent about parameter names.
If the library documentation says that's okay, and considers the
parameter names to be part of the stable interface for the libraries,
then user could can use the names straight away - no library changes are
needed. (It is not uncommon for library documentation to be wholly or
partly generated automatically by tools like doxygen, which do view
parameter names as significant.) If the documentation does not say so,
then the user is taking a risk or tying their code to a specific library
release.
If you as the library implementer want to change a parameter name in the
headers, that's fair enough if you didn't say they would be consistent,
and a breaking change if you did - just like countless other kinds of
changes to a library API. If you want to change the parameter names
inside the implementation code, that's also fine. It would generally be
a bad idea to have them inconsistent with the headers, but it is
certainly allowable - the compiler would accept them, with optional
warnings.
I can't see how you would be any source or binary incompatibilities that
are not basically the same as you get with relying on any other kind of
implementation details that are not guaranteed to be fixed.
Post by Matthew Woehlke
Post by David Brown
Post by Matthew Woehlke
class foo
{
...interface...
FooPrivate* d;
};
No so much "leaked" there...
Well, no, not in a case like this. But when the private section holds
members and possibly inline implementations, it is leaked. This is
especially true of template libraries.
True. The point is that "some libraries are designed poorly" is not an
excuse to leak even *more*.
The use of PIMPLE is /not/ a black-or-white mark of good library design!
And the use of named parameters from the public header information does
not involve /any/ leak that was not already leaked from before.
Post by Matthew Woehlke
Post by David Brown
Post by Matthew Woehlke
Post by David Brown
I don't think your argument against allowing people to use named
parameters for existing functions is at all convincing.
Who's arguing that?
void foo(int x); // note: not a named parameter
foo(.x=5); // okay, but maybe warn in pedantic mode
foo(.a=5); // okay, but probably warn
Do you mean you would be happy to allow the parameter name in an
existing declaration to be used in function calls as a check?
If I make a call with a named parameter that resolves to a function that
does not have explicitly named parameters, then yes, I'm fine with the
compiler *warning* me if the names don't match.
I agree.
Post by Matthew Woehlke
Post by David Brown
But you would presumably not allow such names to be used for
overloads - that would require a specific extra syntax in the
declaration. Is that correct?
Right.
Good.
Post by Matthew Woehlke
I guess in that sense what I'm proposing is opt-out weak naming (that
only involves a possible compiler warning if you mismatch names) with
opt-in strong naming, where the "fun stuff" (argument skipping, and per
your question, name-based overloading) requires 'strong' naming.
Certainly I fully agree that name-based overloading requires "strong"
naming - where the declaration has a new syntax saying that names /must/
be used in some form, and where the parameter names become part of the
ABI for the function. (I hope that could be achieved with name
mangling, or with types somehow, in order to minimise the implementation
changes needed.)
I also think that common use, checked with optional compiler warnings
(which could of course be errors if you choose appropriate compiler
flags), can be done with "weak" naming - using parameter names declared
as they are today in existing code.
No, they can't:

What I have established, having had discussions about named arguments
Post by David Brown
on multiple occasions,
1) it needs to be an opt-in for the author of a library, so no
automagic naming. Some library
authors do not want users relying on names that the library author
didn't expect them to rely
on, in order to avoid breakage that wasn't considered beforehand.
This was suggested back in 1991(!), and rejected!
We need to drop that idea for good *and move on*, *make some progress!*

And no, documenting which arguments are stable API is not good enough.
C++ is trying for 30 years to fix the need for documentation to *use* the
code (concepts), no one needs more of it.

I am saying all this with best intentions - we need to stop repeating the
same mistakes and really, step by step make *some* progress.
Progress in *requirements (what we need)*, but progress in *implementation
(how can be done)*.

...
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/2d87741a-3e1d-4a15-bd84-1aff722a047b%40isocpp.org.
Matthew Woehlke
2018-08-23 16:44:38 UTC
Permalink
Post by David Brown
here I am talking about the optional use of parameter names to improve
readability, help write correct code, help spot incorrect code, and -
optionally - to allow re-arranging of parameter order and skipping
defaults using names.
If we *don't* get the optional parts (skipping, reordering)... then
what's the point?

If we don't get the optional parts, you might as well modify your
compiler to warn you about:

void foo(int x);
foo(/*y=*/5); // warning: 'y' != 'x'

...and no language change is required.
Post by David Brown
There are two other use-cases where there could be debate about the best
If the call has the right parameter names, but the wrong order, should
that be a warning, or error, or should the compiler "magically" correct
the order?  If strong naming is used, the compiler should certainly be
able to re-order the parameters without giving any complaints.
Honestly, this is a good question. There are arguments on both sides
whether or not to allow reordering, and I am somewhat avoiding taking a
stance.

That said, FWIW I think I'm less okay with reordering weak names than
strong names.
Post by David Brown
The other case is for skipping arguments.  Again, with strong naming
this should be supported.  I believe it /could/ be supported fine with
weak naming, but would again be okay with the safer solution of not
allowing it without strong naming.
Agreed. (Skipping is sort of a "weak" form of reordering.)
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/d1905217-f914-6076-55a2-6b92b1880ed9%40gmail.com.
David Brown
2018-08-23 17:17:00 UTC
Permalink
Post by Matthew Woehlke
Post by David Brown
here I am talking about the optional use of parameter names to improve
readability, help write correct code, help spot incorrect code, and -
optionally - to allow re-arranging of parameter order and skipping
defaults using names.
If we *don't* get the optional parts (skipping, reordering)... then
what's the point?
If we don't get the optional parts, you might as well modify your
void foo(int x);
foo(/*y=*/5); // warning: 'y' != 'x'
...and no language change is required.
I see two disadvantages of that. One is that it is seriously ugly
having comments in the middle of a function call - "foo(.y = 5)" is very
much nicer and neater syntax. The other is that because there is no
standard, and neither limits nor requirements in what you might have in
these comments (maybe someone wants to write "foo( /* was 4 in last
version */ 5);", it would be hard to get it in common use.

But as far as I see it, it is this checking that is the most important
feature. It covers the two most vital points - it aids readability and
clarity of the code, and it means mistakes are more likely to be caught
at compile-time. These are both /good/ things - and IMHO they are worth
allowing the syntax "foo(.y = 5);" even if you don't get anything else.

(I'd like to see that same syntax in C as well, including calling C
functions from C++ - and I think re-ordering and overloading would not
be a consideration for C.)
Post by Matthew Woehlke
Post by David Brown
There are two other use-cases where there could be debate about the best
If the call has the right parameter names, but the wrong order, should
that be a warning, or error, or should the compiler "magically" correct
the order?  If strong naming is used, the compiler should certainly be
able to re-order the parameters without giving any complaints.
Honestly, this is a good question. There are arguments on both sides
whether or not to allow reordering, and I am somewhat avoiding taking a
stance.
I have some rough preferences here - but I freely admit that I don't
have the experience at guessing what the complications might be, and I
leave it to the experts to see if the stance is forced by issues that I
have not thought about.
Post by Matthew Woehlke
That said, FWIW I think I'm less okay with reordering weak names than
strong names.
Post by David Brown
The other case is for skipping arguments.  Again, with strong naming
this should be supported.  I believe it /could/ be supported fine with
weak naming, but would again be okay with the safer solution of not
allowing it without strong naming.
Agreed. (Skipping is sort of a "weak" form of reordering.)
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/35f836e7-f7af-e36f-e5f4-2be447d65576%40westcontrol.com.
Matthew Woehlke
2018-08-23 17:37:08 UTC
Permalink
Post by Matthew Woehlke
If we don't get the optional parts, you might as well modify your
   void foo(int x);
   foo(/*y=*/5); // warning: 'y' != 'x'
...and no language change is required.
I see two disadvantages of that.  One is that it is seriously ugly
having comments in the middle of a function call - "foo(.y = 5)" is very
much nicer and neater syntax.  The other is that because there is no
standard, and neither limits nor requirements in what you might have in
these comments (maybe someone wants to write "foo( /* was 4 in last
version */ 5);", it would be hard to get it in common use.
But as far as I see it, it is this checking that is the most important
feature.  It covers the two most vital points - it aids readability and
clarity of the code, and it means mistakes are more likely to be caught
at compile-time.  These are both /good/ things - and IMHO they are worth
allowing the syntax "foo(.y = 5);" even if you don't get anything else.
I understand what you're saying. I just happen to strongly disagree :-).
(That is, I would agree with the above if you replace "most" with
"least"...)

That said, my current vision would give you what you're asking for...
but also overloading and skipping.

Also, as has been elsewhere discussed, I'm not sure how forwarding would
work without at least some degree of "strong" naming, and I don't see
any proposal getting much traction if it doesn't "solve" forwarding.
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/d3a82498-693b-e586-86a2-0af9364a7baf%40gmail.com.
David Brown
2018-08-24 06:31:45 UTC
Permalink
Post by Matthew Woehlke
Post by Matthew Woehlke
If we don't get the optional parts, you might as well modify your
   void foo(int x);
   foo(/*y=*/5); // warning: 'y' != 'x'
...and no language change is required.
I see two disadvantages of that.  One is that it is seriously ugly
having comments in the middle of a function call - "foo(.y = 5)" is very
much nicer and neater syntax.  The other is that because there is no
standard, and neither limits nor requirements in what you might have in
these comments (maybe someone wants to write "foo( /* was 4 in last
version */ 5);", it would be hard to get it in common use.
But as far as I see it, it is this checking that is the most important
feature.  It covers the two most vital points - it aids readability and
clarity of the code, and it means mistakes are more likely to be caught
at compile-time.  These are both /good/ things - and IMHO they are worth
allowing the syntax "foo(.y = 5);" even if you don't get anything else.
I understand what you're saying. I just happen to strongly disagree :-).
(That is, I would agree with the above if you replace "most" with
"least"...)
I think we just have a little difference in perspective. You want
powerful new features, and increased checking and readability is a free
bonus from that. I want increased checking and readability, and new
features might be a bonus from the way they are implemented.
Post by Matthew Woehlke
That said, my current vision would give you what you're asking for...
but also overloading and skipping.
Also, as has been elsewhere discussed, I'm not sure how forwarding would
work without at least some degree of "strong" naming, and I don't see
any proposal getting much traction if it doesn't "solve" forwarding.
We could get /my/ part done without worrying about forwarding...

But I agree it is unlikely that the standards would support a named
parameter system that doesn't cover a wider range of new functions.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/90defe78-0849-1cbd-3835-bc73160ee829%40westcontrol.com.
Matthew Woehlke
2018-08-24 15:28:31 UTC
Permalink
Post by David Brown
We could get /my/ part done without worrying about forwarding...
As others have noted, if we don't even worry about forwarding, I just
can't see where what you are proposing is a sufficient improvement over
what clang-tidy *already does* to be worth committee time...
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/defb4327-c818-a439-ff58-7838d3a046de%40gmail.com.
Vicente J. Botet Escriba
2018-08-24 17:26:40 UTC
Permalink
Post by Matthew Woehlke
Post by David Brown
We could get /my/ part done without worrying about forwarding...
As others have noted, if we don't even worry about forwarding, I just
can't see where what you are proposing is a sufficient improvement over
what clang-tidy *already does* to be worth committee time...
How would you ensure that any developer uses the same syntax so that
clang-tidy takes in account those comments as weak named parameters ? :(

Having weak named parameters in the standard will ensure that everybody
uses the same syntax :)


Vicente
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/dc396379-2e4b-4758-5f1f-51e2561acfa2%40wanadoo.fr.
Matthew Woehlke
2018-08-24 17:39:19 UTC
Permalink
Post by Vicente J. Botet Escriba
Post by Matthew Woehlke
Post by David Brown
We could get /my/ part done without worrying about forwarding...
As others have noted, if we don't even worry about forwarding, I just
can't see where what you are proposing is a sufficient improvement over
what clang-tidy *already does* to be worth committee time...
How would you ensure that any developer uses the same syntax so that
clang-tidy takes in account those comments as weak named parameters ? :(
...because for this purpose, clang-tidy is the *de facto* standard.
Post by Vicente J. Botet Escriba
Having weak named parameters in the standard will ensure that everybody
uses the same syntax :)
Why do you think that a de jure standard will be more closely followed
than a de facto standard? In fact, considering that I can use the de
facto standard "weak arguments" *in C++98*, whereas the hypothetical de
jure standard I can only follow if all my compilers support C++20 or
C++2x, I would rather expect the opposite...
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/4c686121-fd2e-18b0-1480-e2f528c085ef%40gmail.com.
Vicente J. Botet Escriba
2018-08-24 23:10:59 UTC
Permalink
Post by Matthew Woehlke
Post by Vicente J. Botet Escriba
Post by Matthew Woehlke
Post by David Brown
We could get /my/ part done without worrying about forwarding...
As others have noted, if we don't even worry about forwarding, I just
can't see where what you are proposing is a sufficient improvement over
what clang-tidy *already does* to be worth committee time...
How would you ensure that any developer uses the same syntax so that
clang-tidy takes in account those comments as weak named parameters ? :(
...because for this purpose, clang-tidy is the *de facto* standard.
weak named parameters allow reorder and omission of named parameters
having a default value.
AFAIK clang-tidy cannot do that.

For me weak named parameters are parameter that have a specific name
that is part of the public interface of the function (the current ones
are not weak named parameters) and that can be used by the caller to
name the argument but that doesn't change his signature, nor the ABI.
These functions can be called without the use of the names, following
the current rules. parameter names could be used to select the good
overload, but are not part of the signature and so we can not forward
weak parameter names, but it can forward named parameters when we don't
use his name (as we do now).

Maybe you want forwarding, but then the name of the named parameter need
to be part of the signature. IMO, this is solved with tag dispatching
and weak named parameters.
Post by Matthew Woehlke
Post by Vicente J. Botet Escriba
Having weak named parameters in the standard will ensure that everybody
uses the same syntax :)
Why do you think that a de jure standard will be more closely followed
than a de facto standard? In fact, considering that I can use the de
facto standard "weak arguments" *in C++98*, whereas the hypothetical de
jure standard I can only follow if all my compilers support C++20 or
C++2x, I would rather expect the opposite...
Sorry, but we are not talking here about C++98, but a possible feature
for the future standard.

And yes, I'm sure that having them in the standard would make them used
a lot (as they are currently in other languages) than what we can get
with C comments and clang-tidy.


Vicente
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/7d1be349-0a22-e22e-f0e7-e578f7b1c919%40wanadoo.fr.
m***@gmail.com
2018-08-25 05:23:52 UTC
Permalink
On Saturday, August 25, 2018 at 2:11:04 AM UTC+3, Vicente J. Botet Escriba
Post by David Brown
We could get /my/ part done without worrying about forwarding...
As others have noted, if we don't even worry about forwarding, I just
can't see where what you are proposing is a sufficient improvement over
what clang-tidy *already does* to be worth committee time...
How would you ensure that any developer uses the same syntax so that
clang-tidy takes in account those comments as weak named parameters ? :(
...because for this purpose, clang-tidy is the *de facto* standard.
weak named parameters allow reorder and omission of named parameters
having a default value.
AFAIK clang-tidy cannot do that.
For me weak named parameters are parameter that have a specific name that
is part of the public interface of the function (the current ones are not
weak named parameters) and that can be used by the caller to name the
argument but that doesn't change his signature, nor the ABI. These
functions can be called without the use of the names, following the current
rules. parameter names could be used to select the good overload, but are
not part of the signature and so we can not forward weak parameter names,
but it can forward named parameters when we don't use his name (as we do
now).
Maybe you want forwarding, but then the name of the named parameter need
to be part of the signature. IMO, this is solved with tag dispatching and
weak named parameters.
Forwarding is 100% doable as forwarding references are inline and the
compiler can see-through.
What is not possible is forward-as-tuple and async type of forwarding,
where forwarding references are not used all the way down.

Having weak named parameters in the standard will ensure that everybody
Post by David Brown
uses the same syntax :)
Why do you think that a de jure standard will be more closely followed
than a de facto standard? In fact, considering that I can use the de
facto standard "weak arguments" *in C++98*, whereas the hypothetical de
jure standard I can only follow if all my compilers support C++20 or
C++2x, I would rather expect the opposite...
Sorry, but we are not talking here about C++98, but a possible feature for
the future standard.
And yes, I'm sure that having them in the standard would make them used a
lot (as they are currently in other languages) than what we can get with C
comments and clang-tidy.
Vicente
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/293fe1d0-2692-4998-b7d2-f699522c2dec%40isocpp.org.
Vicente J. Botet Escriba
2018-08-26 11:36:29 UTC
Permalink
Post by m***@gmail.com
On Saturday, August 25, 2018 at 2:11:04 AM UTC+3, Vicente J. Botet
Post by Matthew Woehlke
Post by Vicente J. Botet Escriba
Post by Matthew Woehlke
Post by David Brown
We could get /my/ part done without worrying about forwarding...
As others have noted, if we don't even worry about forwarding, I just
can't see where what you are proposing is a sufficient improvement over
what clang-tidy *already does* to be worth committee time...
How would you ensure that any developer uses the same syntax so that
clang-tidy takes in account those comments as weak named parameters ? :(
...because for this purpose, clang-tidy is the *de facto* standard.
BTW, I have not see a clang tidy checker that manage with this; Do you
have a pointer?
Post by m***@gmail.com
weak named parameters allow reorder and omission of named
parameters having a default value.
AFAIK clang-tidy cannot do that.
For me weak named parameters are parameter that have a specific
name that is part of the public interface of the function (the
current ones are not weak named parameters) and that can be used
by the caller to name the argument but that doesn't change his
signature, nor the ABI. These functions can be called without the
use of the names, following the current rules. parameter names
could be used to select the good overload, but are not part of the
signature and so we can not forward weak parameter names, but it
can forward named parameters when we don't use his name (as we do
now).
Maybe you want forwarding, but then the name of the named
parameter need to be part of the signature. IMO, this is solved
with tag dispatching and weak named parameters.
Forwarding is 100% doable as forwarding references are inline and the
compiler can see-through.
What is not possible is forward-as-tuple and async type of forwarding,
where forwarding references are not used all the way down.
It is not important if compilers (the language) could manage with
forwarding weak named parameters if the asynchronous case can not be
managed, isn't it?

Vicente
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/979be82f-a6e6-17f4-f0f8-732b6791ffec%40wanadoo.fr.
David Brown
2018-08-24 14:36:53 UTC
Permalink
Post by Matthew Woehlke
Post by David Brown
Post by Matthew Woehlke
If we don't get the optional parts, you might as well modify your
void foo(int x);
foo(/*y=*/5); // warning: 'y' != 'x'
...and no language change is required.
I see two disadvantages of that. One is that it is seriously ugly
having comments in the middle of a function call - "foo(.y = 5)" is very
much nicer and neater syntax. The other is that because there is no
standard, and neither limits nor requirements in what you might have in
these comments (maybe someone wants to write "foo( /* was 4 in last
version */ 5);", it would be hard to get it in common use.
But as far as I see it, it is this checking that is the most important
feature. It covers the two most vital points - it aids readability and
clarity of the code, and it means mistakes are more likely to be caught
at compile-time. These are both /good/ things - and IMHO they are worth
allowing the syntax "foo(.y = 5);" even if you don't get anything else.
I understand what you're saying. I just happen to strongly disagree :-).
(That is, I would agree with the above if you replace "most" with
"least"...)
That said, my current vision would give you what you're asking for...
but also overloading and skipping.
Also, as has been elsewhere discussed, I'm not sure how forwarding would
work without at least some degree of "strong" naming, and I don't see
any proposal getting much traction if it doesn't "solve" forwarding.
It has just occurred to me that if you allow skipping of overloaded
defaults - which can be done without "strong" naming or changes to
declaration syntax - it is quite easy to implement name-based
overloading in the same way as it is done in Python. For example,
Post by Matthew Woehlke
Post by David Brown
Post by Matthew Woehlke
c = complex(1, 2)
type(c)
<type 'complex'>
Post by Matthew Woehlke
Post by David Brown
Post by Matthew Woehlke
print c
(1+2j)
You might want a function "Complex" that could be used with either polar
or rectangular parameters. In Python, you would define that as
something like:

def Complex(x = None, y = None, r = None, phi = None) :
if (x != None) and (y != None) :
return complex(x, y)
if (r != None) and (phi != None) :
return cmath.rect(r, phi)
raise NotImplementedError
Post by Matthew Woehlke
Post by David Brown
Post by Matthew Woehlke
Complex(1, 2)
(1+2j)
Post by Matthew Woehlke
Post by David Brown
Post by Matthew Woehlke
Complex(x = 1, y = 2)
(1+2j)
Post by Matthew Woehlke
Post by David Brown
Post by Matthew Woehlke
Complex(r = 1, phi = math.pi / 4)
(0.7071067811865476+0.7071067811865475j)

That is simple, name-based overloading.

C++ can express the same thing, using optional:


#include <stdint.h>
#include <complex>
#include <optional>
#include <exception>

using namespace std;

inline complex<double>
Complex(optional<double> x = nullopt, optional<double> y = nullopt,
optional<double> r = nullopt, optional<double> phi = nullopt)
{
if (x && y) return complex<double>(x.value(), y.value());
if (r && phi) return polar(r.value(), phi.value());
throw invalid_argument("Complex requires either x, y /or/ r, phi");
}


complex<double> rect_test1(double a, double b) {
return complex<double>(a, b);
}

complex<double> rect_test2(double a, double b) {
return Complex(a, b);
}

complex<double> polar_test1(double a, double b) {
return polar(a, b);
}

complex<double> polar_test2(double a, double b) {
return Complex(nullopt, nullopt, a, b);
}


Functions rect_test1 and rect_test2 generate the same code in gcc, as do
functions polar_test1 and polar_test2, from a quick test.

If you allow parameter names to skip default values, then using this
function definition for "Complex", without any changes to the code or
language as it is today, you could write:

complex<double> rect_test3(double a, double b) {
return Complex(.x = a, .y = b);
}

complex<double> polar_test3(double a, double b) {
return Complex(.r = a, .phi = b);
}


That gives you parameter name based function overloading without having
to change the language at the definition side, and without more than a
small syntax change on the caller side. (C++ compilers might want to
put some effort into making sure they optimise std::optional well - but
that would be nice anyway!)
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/plp522%24rl7%241%40blaine.gmane.org.
Matthew Woehlke
2018-08-16 14:34:55 UTC
Permalink
Post by David Brown
I am at a loss to why people key wanting to make this such a complicated
issue.
[...]
2. The primary use is to check that parameters are given in the right
order, with the ability to re-order parameters at the call site as a
secondary concern.
...probably because plenty of people disagree with this point. AFAIAC,
any proposal that does NOT allow these:

void foo(int, int :a = 1, int :b = 2, int :c = 12);
foo(3, b: 5); // foo(3, 1, 5, 12)

void bar(int :a);
void bar(int :x); // distinct overload

...is pointless. Checking argument order is, IMHO, not only *not* "the
primary use", but *optional*.
Post by David Brown
3. It should not require changes to existing code, new ABIs, new object
file formats, or anything more than minimal changes to the compiler
front-end.
While I agree we'd like to obtain this, I don't think it's realistic...
which probably has a lot to do with why no proposal has (yet) been accepted.
Post by David Brown
We do /not/ want this to be part of a function's signature - there is no
benefit to it,
Wrong: overloading.

Python doesn't have this problem because a) there is no such thing as
separate declarations and definitions in Python, and b) Python has no
overloading, period.

These aren't the case in C++, and trying to ignore the ramifications of
these points as they apply to named arguments is IMO a recipe for failure.

Also, forwarding needs to work somehow. I don't see how this can be done
without making names part of the type system.
Post by David Brown
(But the added complexity and implementation effort needed would not
be worth it - such costly ideas hinder the adoption of the main
feature. And there would be nothing to stop this being added in some
way at a later date.)
I disagree; if you make named arguments *not* part of the ABI, I think
it will be very hard to go back and change that decision.
Post by David Brown
foo(.b = 2, .a = 1, 3);
This is confusing, and IMO should be prohibited. Just like it is in Python.
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/af7b98cc-be81-e6cd-667d-c1b56abe7514%40gmail.com.
David Brown
2018-08-16 14:53:47 UTC
Permalink
Post by Matthew Woehlke
Post by David Brown
I am at a loss to why people key wanting to make this such a complicated
issue.
[...]
2. The primary use is to check that parameters are given in the right
order, with the ability to re-order parameters at the call site as a
secondary concern.
...probably because plenty of people disagree with this point. AFAIAC,
void foo(int, int :a = 1, int :b = 2, int :c = 12);
foo(3, b: 5); // foo(3, 1, 5, 12)
My proposal allows that. It just doesn't need any change to the
declaration to make it work:

void foo(int, int a = 1, int b = 2, int c = 12);
foo(3, b: 5); // foo(3, 1, 5, 12)

(I suggested the syntax "foo(3, .b = 5)" - but I would be perfectly
happy with alternatives like "foo(3, b: 5)".)
Post by Matthew Woehlke
void bar(int :a);
void bar(int :x); // distinct overload
...is pointless.
I disagree. Distinct overloads like this would be nice, but (as I
wrote) extremely costly in terms of changes to implementations and
existing software. I would rather see that as a later enhancement once
we have the simple named parameters in place - my proposal does not
conflict with having this as a later feature.
Post by Matthew Woehlke
Checking argument order is, IMHO, not only *not* "the
primary use", but *optional*.
Checking argument order is absolutely the key point in terms of helping
people write correct code by spotting errors at compile time. It is
also key to making code clearer by documenting parameters better without
ugly "/* parameter_name */" comments.

Those would be two /huge/ benefits to today's language, and can be
implemented easily and cheaply.

Allowing a re-arrangement of the order of parameters would be another
big benefit for not much higher cost, and is also something I would want.

The cost-benefit relation for name-based overload is very different.
While I would also like it, I would hate to see simple, useful named
parameters blocked or delayed while people fight over this feature.
Post by Matthew Woehlke
Post by David Brown
3. It should not require changes to existing code, new ABIs, new object
file formats, or anything more than minimal changes to the compiler
front-end.
While I agree we'd like to obtain this, I don't think it's realistic...
which probably has a lot to do with why no proposal has (yet) been accepted.
My proposal would not require any changes to these things. The reason
no proposal has been accepted is because people demand too much - such
as name-based overloads - that block the simple features.
Post by Matthew Woehlke
Post by David Brown
We do /not/ want this to be part of a function's signature - there is no
benefit to it,
Wrong: overloading.
Yes, you are right - you need the names to be part of the signature for
name-based overloading. That is a key reason why name-based overloading
should not be part of a first step for named parameters - it avoids this
massive change.
Post by Matthew Woehlke
Python doesn't have this problem because a) there is no such thing as
separate declarations and definitions in Python, and b) Python has no
overloading, period.
These aren't the case in C++, and trying to ignore the ramifications of
these points as they apply to named arguments is IMO a recipe for failure.
Also, forwarding needs to work somehow. I don't see how this can be done
without making names part of the type system.
It is very simple - as long as you drop name-based overloading. Named
parameters can be based purely and completely on function declarations -
nothing else. If you want to forward to different function, use the
names declared for that function. If you want to use a function
pointer, use the names given in the declaration for that function
pointer. If there are no names given, you can't use named parameters.
Post by Matthew Woehlke
Post by David Brown
(But the added complexity and implementation effort needed would not
be worth it - such costly ideas hinder the adoption of the main
feature. And there would be nothing to stop this being added in some
way at a later date.)
I disagree; if you make named arguments *not* part of the ABI, I think
it will be very hard to go back and change that decision.
I think it is important to consider how they might be added later, and
what effect that would have - and if possible leave the door open for
name-based overloads in future versions.

But if the choice came down to named parameters without name-based
overloads implemented now, or waiting for an all-singing all-dancing
version some time in the future, I have not the slightest doubt which I
would pick.
Post by Matthew Woehlke
Post by David Brown
foo(.b = 2, .a = 1, 3);
This is confusing, and IMO should be prohibited. Just like it is in Python.
I would not object to it being prohibited.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/5B758FFB.40507%40westcontrol.com.
Matthew Woehlke
2018-08-16 16:25:18 UTC
Permalink
Post by David Brown
Post by Matthew Woehlke
Checking argument order is, IMHO, not only *not* "the
primary use", but *optional*.
Checking argument order is absolutely the key point in terms of helping
people write correct code by spotting errors at compile time. It is
also key to making code clearer by documenting parameters better without
ugly "/* parameter_name */" comments.
Those would be two /huge/ benefits to today's language, and can be
implemented easily and cheaply.
While I don't disagree with that, exactly, I also don't see it as a
compelling benefit. For me, named arguments are *primarily* about fixing
the problem of needing extremely flexible functions (read: large number
of parameters and/or large number of overloads) of which any *one* user
is only going to care about a small slice of the total surface area. I
only care about argument order to the extent it is useful in solving
that problem. Thus, for me, *the* killer features are being able to
specify one parameter in the middle of a list of defaulted parameters,
and/or to overload on parameter names.

If I don't get those, I'd rather not muddy the feature space with
anything else.
Post by David Brown
Yes, you are right - you need the names to be part of the signature for
name-based overloading. That is a key reason why name-based overloading
should not be part of a first step for named parameters - it avoids this
massive change.
[...]
[Forwarding] is very simple - as long as you drop name-based overloading.
[...]
I think it is important to consider how they might be added later, and
what effect that would have - and if possible leave the door open for
name-based overloads in future versions.
Right, so... here's an experiment. Explain how we could *later* add
name-based overloading on top of your proposal.

If you can't do that, then accepting your proposal means we can *never*
have name-based overloading. Which means everyone that wants that is
going to be opposed to your proposal.

If you *can* do that, I think it would make your proposal much more
compelling.
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/4f2cea6a-f66e-0305-41da-50f2d2ebf69c%40gmail.com.
m***@gmail.com
2018-08-16 17:10:44 UTC
Permalink
Post by Matthew Woehlke
Post by David Brown
Post by Matthew Woehlke
Checking argument order is, IMHO, not only *not* "the
primary use", but *optional*.
Checking argument order is absolutely the key point in terms of helping
people write correct code by spotting errors at compile time. It is
also key to making code clearer by documenting parameters better without
ugly "/* parameter_name */" comments.
Those would be two /huge/ benefits to today's language, and can be
implemented easily and cheaply.
While I don't disagree with that, exactly, I also don't see it as a
compelling benefit. For me, named arguments are *primarily* about fixing
the problem of needing extremely flexible functions (read: large number
of parameters and/or large number of overloads) of which any *one* user
is only going to care about a small slice of the total surface area. I
only care about argument order to the extent it is useful in solving
that problem. Thus, for me, *the* killer features are being able to
specify one parameter in the middle of a list of defaulted parameters,
and/or to overload on parameter names.
Why overloading is so important to you? Because the first request is doable
(default-by-mention or full rearrange), but the last is a *nightmare* to
define *and* is doable today via workarounds.

Can you please define names change the signature? Is this some sort of
name-type pair? Is it a tag? Is this pure compiler help or part of the type
system?

And again, why is a killer?
Post by Matthew Woehlke
If I don't get those, I'd rather not muddy the feature space with
anything else.
Post by David Brown
Yes, you are right - you need the names to be part of the signature for
name-based overloading. That is a key reason why name-based overloading
should not be part of a first step for named parameters - it avoids this
massive change.
[...]
[Forwarding] is very simple - as long as you drop name-based
overloading.
Post by David Brown
[...]
I think it is important to consider how they might be added later, and
what effect that would have - and if possible leave the door open for
name-based overloads in future versions.
Right, so... here's an experiment. Explain how we could *later* add
name-based overloading on top of your proposal.
If you can't do that, then accepting your proposal means we can *never*
have name-based overloading. Which means everyone that wants that is
going to be opposed to your proposal.
If you *can* do that, I think it would make your proposal much more
compelling.
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/77719fdf-0f81-4c24-ad56-91826ef73032%40isocpp.org.
Matthew Woehlke
2018-08-16 17:29:30 UTC
Permalink
Post by m***@gmail.com
Why overloading is so important to you? Because the first request is doable
(default-by-mention or full rearrange), but the last is a *nightmare* to
define *and* is doable today via workarounds.
vector<int> x{values: 1};
vector<int> x{reserve: 1};

complex{imag: 1};
complex{r: 1, t: 90};

Is it *killer*? Maybe, maybe not. But that's not the point. IMHO, the
burden of proof should be on the one(s) arguing for an implementation
that seems to preclude *ever* getting name overload to either show a)
why we will *never* need/want this feature, or b) how it could still be
implemented, later.

I'd rather have no feature than a half-baked feature that can't ever be
made better.
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/3aaded76-362a-7fc7-9d00-5f505b4d1385%40gmail.com.
m***@gmail.com
2018-08-16 18:40:03 UTC
Permalink
Post by m***@gmail.com
Post by m***@gmail.com
Why overloading is so important to you? Because the first request is
doable
Post by m***@gmail.com
(default-by-mention or full rearrange), but the last is a *nightmare* to
define *and* is doable today via workarounds.
vector<int> x{values: 1};
vector<int> x{reserve: 1};
complex{imag: 1};
complex{r: 1, t: 90};
Is it *killer*? Maybe, maybe not. But that's not the point. IMHO, the
burden of proof should be on the one(s) arguing for an implementation
that seems to preclude *ever* getting name overload to either show a)
why we will *never* need/want this feature, or b) how it could still be
implemented, later.
I'd rather have no feature than a half-baked feature that can't ever be
made better.
The point was to define how it would work.

vector<int> x{values: 1};
vector<int> x{reserve: 1};

This is doable with tags. And we can improve them
<https://groups.google.com/a/isocpp.org/d/msg/std-proposals/tPtdQE2GXb0/4OjT5Z4pBQAJ>

complex{imag: 1};
complex{r: 1, t: 90};

This is already overloaded, no need for strong names.


BTW, I am not against *any* use case you would come up with, as I said I am
pro named arguments,
not only that, *I believe we need both that change the signature and the
ones that don't!*

However, the ones that *do* change the signature are, in practice, *both
less common and easier to work around*!
And, the ones that do *not* need overload are more common and often very
clumsy to work around.

As for future proofing - *there is no problem if we support both*

rect(Point topLeft: pos, Point bottomRight: br); //< weak argument names,
not mandatory

// later in some future

rect(center: Point pos, Point bottomRight: br) //< strong argument name,
adds an overload, not ignorable


All the old code will work, but now center: is mandatory and *will*
overload.

How would this work? Well, the easiest is to be a tag, as already explored.
But it could be a modifier to Point or some automagic shortcut to std::pair<"center",
Point>

And again, weak named argument are somewhat easier and not less useful
(unless they are just warnings)
and not mutually exclusive to strong ones!
Post by m***@gmail.com
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/ee206ac4-f7e6-4c37-a4d3-a3f5f90bbcbb%40isocpp.org.
Matthew Woehlke
2018-08-16 18:49:26 UTC
Permalink
Post by m***@gmail.com
This is already overloaded, no need for strong names.
Eh? Both of those functions, without names have / would have the
signature (double, double). Without strong names, that would be ambiguous.
Post by m***@gmail.com
As for future proofing - *there is no problem if we support both*
rect(Point topLeft: pos, Point bottomRight: br); //< weak argument names,
not mandatory
// later in some future
rect(center: Point pos, Point bottomRight: br) //< strong argument name,
adds an overload, not ignorable
How would... oh, wait, you're proposing to differentiate strong vs. weak
names *based on position*? That's confusing as all else. I can't imagine
that would *ever* be approved.
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e3b83d23-a855-cda6-e167-9fed1889ff37%40gmail.com.
m***@gmail.com
2018-08-16 19:54:06 UTC
Permalink
Post by Matthew Woehlke
Post by m***@gmail.com
This is already overloaded, no need for strong names.
Eh? Both of those functions, without names have / would have the
signature (double, double). Without strong names, that would be ambiguous.
Ok I skimmed a bit too fast.

As I said, I will not deny any use case, but the workarounds are not hard
and some would argue more correct in this case, like making angle a
different type.
Post by Matthew Woehlke
Post by m***@gmail.com
As for future proofing - *there is no problem if we support both*
rect(Point topLeft: pos, Point bottomRight: br); //< weak argument
names,
Post by m***@gmail.com
not mandatory
// later in some future
rect(center: Point pos, Point bottomRight: br) //< strong argument name,
adds an overload, not ignorable
How would... oh, wait, you're proposing to differentiate strong vs. weak
names *based on position*? That's confusing as all else. I can't imagine
that would *ever* be approved.
Yet, it is learnable and does not require extra syntax.

That was not the point, the point is - we need both - one can't just say
"named arguments are like this" and stick to only one type.

*Both* are useful, but for different things
- weak as semantic disambiguation (for the reader) and conformation (from
the compiler), where using type is incorrect/impractical/maintenance
toll/code size toll,
and, eventually for some sort of typing shortcut
- strong as "named constructors", almost exclusively.

Note that strong can't be used for the purpose of weak, because this will
be extremely annoying (*chough* Objective C)
Post by Matthew Woehlke
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/2b6f559c-95cd-4527-9826-0a9a88d0e463%40isocpp.org.
Nicol Bolas
2018-08-16 20:05:47 UTC
Permalink
Post by m***@gmail.com
Post by Matthew Woehlke
Post by m***@gmail.com
This is already overloaded, no need for strong names.
Eh? Both of those functions, without names have / would have the
signature (double, double). Without strong names, that would be ambiguous.
Ok I skimmed a bit too fast.
As I said, I will not deny any use case, but the workarounds are not hard
and some would argue more correct in this case, like making angle a
different type.
Post by Matthew Woehlke
Post by m***@gmail.com
As for future proofing - *there is no problem if we support both*
rect(Point topLeft: pos, Point bottomRight: br); //< weak argument
names,
Post by m***@gmail.com
not mandatory
// later in some future
rect(center: Point pos, Point bottomRight: br) //< strong argument
name,
Post by m***@gmail.com
adds an overload, not ignorable
How would... oh, wait, you're proposing to differentiate strong vs. weak
names *based on position*? That's confusing as all else. I can't imagine
that would *ever* be approved.
Yet, it is learnable and does not require extra syntax.
There are a lot of things in C++ that are "learnable". SFINAE is
"learnable". "Uniform" initialization is "learnable". The "Most Vexing
Parse" is "learnable".

But I think we can make a distinction between things whose behavior is
fairly obvious and things whose behavior requires significant learning
before it can be understood. What you're talking about seems more like the
latter.

That was not the point, the point is - we need both - one can't just say
Post by m***@gmail.com
"named arguments are like this" and stick to only one type.
*Both* are useful, but for different things
- weak as semantic disambiguation (for the reader) and conformation (from
the compiler), where using type is incorrect/impractical/maintenance
toll/code size toll,
and, eventually for some sort of typing shortcut
- strong as "named constructors", almost exclusively.
Note that strong can't be used for the purpose of weak, because this will
be extremely annoying (*chough* Objective C)
The question therefore is whether we need "weak semantic disambiguation and
confirmation" as a language feature at all.

Strong named parameters actually *do something*; they allow us to express
things that either couldn't be done before or were very inconvenient to do.

Weak named parameters by contrast are mere notation. So why is it important
that we have a language feature for that?

Equally importantly, there are costs to having both. Two separate syntaxes
for something that most languages handle with one. Two separate syntaxes
that have to fight for space in the same area (function parameters). Will
they be reasonably distinct from one another? Is not having two syntaxes
that do subtly different things not inherently confusing?
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/f9b31cb2-ccf1-4c02-aa0c-c10fcda611a7%40isocpp.org.
m***@gmail.com
2018-08-16 21:38:49 UTC
Permalink
Post by Nicol Bolas
Post by m***@gmail.com
Post by Matthew Woehlke
Post by m***@gmail.com
This is already overloaded, no need for strong names.
Eh? Both of those functions, without names have / would have the
signature (double, double). Without strong names, that would be ambiguous.
Ok I skimmed a bit too fast.
As I said, I will not deny any use case, but the workarounds are not hard
and some would argue more correct in this case, like making angle a
different type.
Post by Matthew Woehlke
Post by m***@gmail.com
As for future proofing - *there is no problem if we support both*
rect(Point topLeft: pos, Point bottomRight: br); //< weak argument
names,
Post by m***@gmail.com
not mandatory
// later in some future
rect(center: Point pos, Point bottomRight: br) //< strong argument
name,
Post by m***@gmail.com
adds an overload, not ignorable
How would... oh, wait, you're proposing to differentiate strong vs. weak
names *based on position*? That's confusing as all else. I can't imagine
that would *ever* be approved.
Yet, it is learnable and does not require extra syntax.
There are a lot of things in C++ that are "learnable". SFINAE is
"learnable". "Uniform" initialization is "learnable". The "Most Vexing
Parse" is "learnable".
But I think we can make a distinction between things whose behavior is
fairly obvious and things whose behavior requires significant learning
before it can be understood. What you're talking about seems more like the
latter.
That was not the point, the point is - we need both - one can't just say
Post by m***@gmail.com
"named arguments are like this" and stick to only one type.
*Both* are useful, but for different things
- weak as semantic disambiguation (for the reader) and conformation
(from the compiler), where using type is incorrect/impractical/maintenance
toll/code size toll,
and, eventually for some sort of typing shortcut
- strong as "named constructors", almost exclusively.
Note that strong can't be used for the purpose of weak, because this will
be extremely annoying (*chough* Objective C)
The question therefore is whether we need "weak semantic disambiguation
and confirmation" as a language feature at all.
Strong named parameters actually *do something*; they allow us to express
things that either couldn't be done before or were very inconvenient to do.
Weak named parameters by contrast are mere notation. So why is it
important that we have a language feature for that?
They fix the last semantic hole that neither Types nor Contracts can fix.
Types bound what the item is, contracts bound what value the item has,
names bound what the meaning of the item is.

Often meaning is inferred form type but often this is not possible (math,
physics) or simply incorrect semantically - MotherName is wrong kind of
type.
And often meaning is inferred from the variables themselves, but that is
not enforceable.

Yet, passing an argument, meaning something different is, for all intend
and proposes, a breach of contract, no matter if this is a form on paper to
fill with a pen or a function call.

Can this be solved by types - only if workaround is solving
Can this be solved by strong names - well, yeah, at the price of thinking
the users are idiots having them to repeat like monkeys every name that "we
think it is important".
Post by Nicol Bolas
Equally importantly, there are costs to having both.
Two separate syntaxes for something that most languages handle with one.
Two separate syntaxes that have to fight for space in the same area
Post by Nicol Bolas
(function parameters). Will they be reasonably distinct from one another?
Is not having two syntaxes that do subtly different things not inherently
confusing?
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/11cc494e-2a76-4032-8668-e11c199d4a36%40isocpp.org.
Nicol Bolas
2018-08-16 22:08:45 UTC
Permalink
Post by m***@gmail.com
Post by Nicol Bolas
Post by m***@gmail.com
Post by Matthew Woehlke
Post by m***@gmail.com
This is already overloaded, no need for strong names.
Eh? Both of those functions, without names have / would have the
signature (double, double). Without strong names, that would be ambiguous.
Ok I skimmed a bit too fast.
As I said, I will not deny any use case, but the workarounds are not
hard and some would argue more correct in this case, like making angle a
different type.
Post by Matthew Woehlke
Post by m***@gmail.com
As for future proofing - *there is no problem if we support both*
rect(Point topLeft: pos, Point bottomRight: br); //< weak argument
names,
Post by m***@gmail.com
not mandatory
// later in some future
rect(center: Point pos, Point bottomRight: br) //< strong argument
name,
Post by m***@gmail.com
adds an overload, not ignorable
How would... oh, wait, you're proposing to differentiate strong vs. weak
names *based on position*? That's confusing as all else. I can't imagine
that would *ever* be approved.
Yet, it is learnable and does not require extra syntax.
There are a lot of things in C++ that are "learnable". SFINAE is
"learnable". "Uniform" initialization is "learnable". The "Most Vexing
Parse" is "learnable".
But I think we can make a distinction between things whose behavior is
fairly obvious and things whose behavior requires significant learning
before it can be understood. What you're talking about seems more like the
latter.
That was not the point, the point is - we need both - one can't just say
Post by m***@gmail.com
"named arguments are like this" and stick to only one type.
*Both* are useful, but for different things
- weak as semantic disambiguation (for the reader) and conformation
(from the compiler), where using type is incorrect/impractical/maintenance
toll/code size toll,
and, eventually for some sort of typing shortcut
- strong as "named constructors", almost exclusively.
Note that strong can't be used for the purpose of weak, because this
will be extremely annoying (*chough* Objective C)
The question therefore is whether we need "weak semantic disambiguation
and confirmation" as a language feature at all.
Strong named parameters actually *do something*; they allow us to
express things that either couldn't be done before or were very
inconvenient to do.
Weak named parameters by contrast are mere notation. So why is it
important that we have a language feature for that?
They fix the last semantic hole that neither Types nor Contracts can fix.
Types bound what the item is, contracts bound what value the item has,
names bound what the meaning of the item is.
Often meaning is inferred form type but often this is not possible (math,
physics) or simply incorrect semantically - MotherName is wrong kind of
type.
And often meaning is inferred from the variables themselves, but that is
not enforceable.
Yet, passing an argument, meaning something different is, for all intend
and proposes, a breach of contract, no matter if this is a form on paper to
fill with a pen or a function call.
Your argument makes more sense for strong names than weak ones. After all,
if "meaning something different" is truly a "breach of contract" (and
therefore an error), then that contract is important enough to be stated
whenever the function is used. If I've written a function that needs to
test this "contract", then I want everyone who calls it to actually provide
the correct information.

And if the contract is not important enough to be stated explicitly, then
why does it need to be said at all. How can a contract be *optional*? And I
don't mean in the Contracts proposal way, where compiler options/`axiom`
can turn them on or off. I mean in that each individual use has the ability
to pick and choose whether to provide this "meaning" or not.

Or to put it another way, the only reason "override" is optional is that it
would be a huge compatibility break to make it mandatory. That feature is
very similar to here: both cases are stating the meaning of something
explicitly.

Why is this meaning important enough to be said and verified sometimes and
not other-times?

Lastly, a big problem I have with your conception of weak names is that
you're trying to make them a full-fledged piece of information connected
with a value (in order to make forwarding work)... but you're not using any
existing C++ mechanism to provide this channel of information. Names aren't
types. They aren't values. They're associated with parameter names, but
they have to be able to pass through `std::forward` somehow. And users have
to be able to pass them to non-named functions (like loggers) as well as
named ones.

The various strong naming proposals make these names actual parts of the
C++ language. Some make them into values passed into the function. Others
make the function take an unnamed struct. And so forth.

Weak names can't work through normal C++ channels of information.

Can this be solved by types - only if workaround is solving
Post by m***@gmail.com
Can this be solved by strong names - well, yeah, at the price of thinking
the users are idiots having them to repeat like monkeys every name that "we
think it is important".
To the degree that I think named parameters are important enough to have in
the language, I will happily pay the price of the latter if it means not
having to pay the price of having *two syntaxes* for things that are
essentially the same thing.

It's bad enough that we're creating two separate names for a parameter at
all (the in-function name and the out-of-function name). Let's not compound
this folly by having two ways to set the out-of-function name that have
slightly different meanings.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/9815a651-d02b-4044-b777-77356ced5a8e%40isocpp.org.
m***@gmail.com
2018-08-17 17:19:40 UTC
Permalink
Post by Nicol Bolas
Post by m***@gmail.com
Post by Nicol Bolas
Post by m***@gmail.com
Post by Matthew Woehlke
Post by m***@gmail.com
This is already overloaded, no need for strong names.
Eh? Both of those functions, without names have / would have the
signature (double, double). Without strong names, that would be ambiguous.
Ok I skimmed a bit too fast.
As I said, I will not deny any use case, but the workarounds are not
hard and some would argue more correct in this case, like making angle a
different type.
Post by Matthew Woehlke
Post by m***@gmail.com
As for future proofing - *there is no problem if we support both*
rect(Point topLeft: pos, Point bottomRight: br); //< weak argument
names,
Post by m***@gmail.com
not mandatory
// later in some future
rect(center: Point pos, Point bottomRight: br) //< strong argument
name,
Post by m***@gmail.com
adds an overload, not ignorable
How would... oh, wait, you're proposing to differentiate strong vs. weak
names *based on position*? That's confusing as all else. I can't imagine
that would *ever* be approved.
Yet, it is learnable and does not require extra syntax.
There are a lot of things in C++ that are "learnable". SFINAE is
"learnable". "Uniform" initialization is "learnable". The "Most Vexing
Parse" is "learnable".
But I think we can make a distinction between things whose behavior is
fairly obvious and things whose behavior requires significant learning
before it can be understood. What you're talking about seems more like the
latter.
That was not the point, the point is - we need both - one can't just say
Post by m***@gmail.com
"named arguments are like this" and stick to only one type.
*Both* are useful, but for different things
- weak as semantic disambiguation (for the reader) and conformation
(from the compiler), where using type is incorrect/impractical/maintenance
toll/code size toll,
and, eventually for some sort of typing shortcut
- strong as "named constructors", almost exclusively.
Note that strong can't be used for the purpose of weak, because this
will be extremely annoying (*chough* Objective C)
The question therefore is whether we need "weak semantic disambiguation
and confirmation" as a language feature at all.
Strong named parameters actually *do something*; they allow us to
express things that either couldn't be done before or were very
inconvenient to do.
Weak named parameters by contrast are mere notation. So why is it
important that we have a language feature for that?
They fix the last semantic hole that neither Types nor Contracts can fix.
Types bound what the item is, contracts bound what value the item has,
names bound what the meaning of the item is.
Often meaning is inferred form type but often this is not possible (math,
physics) or simply incorrect semantically - MotherName is wrong kind of
type.
And often meaning is inferred from the variables themselves, but that is
not enforceable.
Yet, passing an argument, meaning something different is, for all intend
and proposes, a breach of contract, no matter if this is a form on paper to
fill with a pen or a function call.
Your argument makes more sense for strong names than weak ones. After all,
if "meaning something different" is truly a "breach of contract" (and
therefore an error), then that contract is important enough to be stated
whenever the function is used. If I've written a function that needs to
test this "contract", then I want everyone who calls it to actually provide
the correct information.
And if the contract is not important enough to be stated explicitly, then
why does it need to be said at all. How can a contract be *optional*? And
I don't mean in the Contracts proposal way, where compiler options/`axiom`
can turn them on or off. I mean in that each individual use has the ability
to pick and choose whether to provide this "meaning" or not.
It is not optional, but the help writing them is.
So ok, weak names are helpers writing correctly the contract, not the
contract itself. They are like a clerk - you can ask him for help, you can
ask him to verify OR you can do it yourself if you know what you are doing.
Post by Nicol Bolas
Or to put it another way, the only reason "override" is optional is that
it would be a huge compatibility break to make it mandatory. That feature
is very similar to here: both cases are stating the meaning of something
explicitly.
Why is this meaning important enough to be said and verified sometimes and
not other-times?
Lastly, a big problem I have with your conception of weak names is that
you're trying to make them a full-fledged piece of information connected
with a value (in order to make forwarding work)... but you're not using any
existing C++ mechanism to provide this channel of information. Names aren't
types. They aren't values. They're associated with parameter names, but
they have to be able to pass through `std::forward` somehow. And users have
to be able to pass them to non-named functions (like loggers) as well as
named ones.
Agreed, for better or worse names are outside the language as defined use
today. Probably the closest are attributes. Super pretty attributes. We
just need a way to mark (or hardcode) std::forward as forwarding them

And BTW, it is not some my conception - C# uses weak names for 10 years
now, pure compiler syntax, outside of types or function signature.

Also, it should be noted it is the weak ones that were proposed for C++ for
26 years now. People just seem to need some extra level of (trivial to get)
protection and explicitness.
Post by Nicol Bolas
The various strong naming proposals make these names actual parts of the
C++ language. Some make them into values passed into the function. Others
make the function take an unnamed struct. And so forth.
Weak names can't work through normal C++ channels of information.
Can this be solved by types - only if workaround is solving
Post by m***@gmail.com
Can this be solved by strong names - well, yeah, at the price of thinking
the users are idiots having them to repeat like monkeys every name that "we
think it is important".
To the degree that I think named parameters are important enough to have
in the language, I will happily pay the price of the latter if it means not
having to pay the price of having *two syntaxes* for things that are
essentially the same thing.
They are not the same, and languages that have only one syntax pick one or
another - C# weak, Objective C- strong.

I am not proposing something concretely, just saying both are valuable, and
theoretically we could have both.

As said, the only reason I would prefer to get weak first, is because the
others are easier to workaround.

And I do believe having mandatory only names will be very annoying - after
all you would need at most one or two strongs to disambiguate and all the
others will be a pain.
Or, we would need extra syntax to make some names optional (ala Swift), but
then, well, we have both strong and weak syntaxes, don't we?

rect(center c: Point, _ br: Point) //< Swift "two syntaxes" mandatory and
optional
Post by Nicol Bolas
It's bad enough that we're creating two separate names for a parameter at
all (the in-function name and the out-of-function name). Let's not compound
this folly by having two ways to set the out-of-function name that have
slightly different meanings.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/d4a4186a-2697-4ce7-8936-335a99a0c362%40isocpp.org.
Jake Arkinstall
2018-08-17 18:08:52 UTC
Permalink
Post by Matthew Woehlke
Post by Justin Bassett
I agree for the most part, but I disagree that this should be a valid
void bar(int :a);
void bar(int :x);
The problem is that bar(4) is ambiguous.
So what?
void foo(int, double=1.);
void foo(int, int=2);
foo(1); // error: ambiguous
TRWTF is the fact that the second function definition is even allowed in
the first place - IMO it should be (and have always been) a 'redefinition'
error. But I do see your point.
Post by Matthew Woehlke
Overloading on name-only parameters is just fine.
What is a "name only" parameter?
I imagine it's a parameter that you can *only* provide by specifying the
name.
Post by Matthew Woehlke
Post by Justin Bassett
Post by Matthew Woehlke
foo(int :a, int :b = 3, int :c = 12);
foo(1, c: 6); // name *must* be used here because 'b' is omitted
Ah. That does demolish my idea about using strong types as named wrappers
for the underlying type.
Well... yes and no. "Strong types as named wrappers for the underlying
type" sounds suspiciously like where my own thoughts on this matter have
been going. However, while I would envision a library/type component, we
do *need* language-level support... not just for syntactic sugar, but
for this, specifically. (And since this is my #1 "killer feature" for
named arguments... don't get me wrong, tagged dispatch / named overload
is #2, but skipping arguments is #1 :-).)
That's where we differ. Only because skipping arguments tends to lead to
sloppy interfaces (but I believe we agree to disagree on this - it is a
matter of personal preference).
Post by Matthew Woehlke
Post by Justin Bassett
Well, it makes it insufficient, at least - in order to make it work
we'd need to change the language to keep trying parameter ordering
until the types fit.
Unlike an approach that changes mangling directly, this does mean that
the
Post by Justin Bassett
foo(const int& a=1, const std::string& b="hello");
foo("world"); //yuck
Which, innocent enough in this example, is going to be a source of bugs
when an implicit conversion exists - unless that ordering search matches
act as explicit, which is going to cause its own problems in terms of
usability.
I would not allow skipping for unnamed parameters.
That's the catch, though.

I suggested using a strong type mechanism for named parameters as a
high-level solution. It just requires generating a struct from the named
parameter at the declaration site, and reinterpreting the input as that
struct when named through the call site (reinterpreting it as the expected
type before entering the function itself). This can be done relatively
early in translation (or even by running code through a few lines of perl
before compilation). As such, it doesn't require changing that much in the
language (in particular, mangling and selecting the right call at the call
site - that's handled indirectly just by introducing the types).

But this high-level solution doesn't suffice if we also want to have a
special case (parameter skipping) - it would be more consistent to just
make it apply to all function calls (which makes me nervous). The only way
I can imagine it COULD work using this approach, but allowing skipping only
for these calls, is if we generate the 2^N possible function calls (N:
number of arguments with defaults) as unique symbols.

If we want to make the parameters rearrangeable too (which would make sense
if we really want to get pythonic bag-functions), all (sum_{k=0}^{N} N!/k!)
possible combinations. That's... horrifying. At least if we enable the
parameter skipping for ordinary functions too, we can get away with N!
symbols (scary, albeit less so than (sum_{k=0}^{N} N!/k!)).

If we allow skipping AND reordering of function arguments for normal
(un-named) calls, such that:

f(S=a, T b=0, U c=0);
f(U{},S{}) // okay

Then we'd be back to the status quo with a single symbol. But obviously,
that would make the language completely unstable.


So unless I'm missing something (which is likely, this stuff isn't my
forte), allowing skipping (and/or reordering) just for these will require a
language change at a later translation phase. And in a later translation
phase, the strong type approach seems rather pointless - it could just be
done directly by the compiler, however the compiler wants to do it.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAC%2B0CCNRg8pi47D1O4BArt8xo%3D3pMGPFTtuQEMzzmPHuYAf-Cg%40mail.gmail.com.
Matthew Woehlke
2018-08-17 18:55:19 UTC
Permalink
Post by Jake Arkinstall
Post by Matthew Woehlke
What is a "name only" parameter?
I imagine it's a parameter that you can *only* provide by specifying the
name.
I assume so also. I don't think we need those as such; not at the
declaration level, certainly.

There will be cases where *calling* a function will need a name, either
due to skipping params or to disambiguate overloads that differ only by
explicit parameter names. But I don't think we need a mechanism that
says 'we will not let you call this function unless you explicitly give
the name' (overload ambiguities aside).
Post by Jake Arkinstall
Post by Matthew Woehlke
[...] skipping arguments is #1 :-).
That's where we differ. Only because skipping arguments tends to lead to
sloppy interfaces (but I believe we agree to disagree on this - it is a
matter of personal preference).
They aren't ideal, but I've run into plenty of instances where I need a
function that has quite a few "knobs", of which the user will likely
never need all of them at any given call site, but *which* ones vary.

Right now the solution is to have a lot of overloads with the arguments
in different orders. This is ugly, a pain to maintain, and possibly
inefficient.
Post by Jake Arkinstall
Post by Matthew Woehlke
I would not allow skipping for unnamed parameters.
That's the catch, though.
I suggested using a strong type mechanism for named parameters as a
high-level solution. It just requires generating a struct from the named
parameter at the declaration site, and reinterpreting the input as that
struct when named through the call site (reinterpreting it as the expected
type before entering the function itself). This can be done relatively
early in translation (or even by running code through a few lines of perl
before compilation). As such, it doesn't require changing that much in the
language (in particular, mangling and selecting the right call at the call
site - that's handled indirectly just by introducing the types).
But this high-level solution doesn't suffice if we also want to have a
special case (parameter skipping) - it would be more consistent to just
make it apply to all function calls (which makes me nervous). The only way
I can imagine it COULD work using this approach, but allowing skipping only
number of arguments with defaults) as unique symbols.
Doesn't the struct approach with designated initializers take care of
this, though?

Anyway, my own current thoughts are not to use a struct, but to make
each named parameter something like `arg<int, "foo"_lit>`. Where we need
language support, then, is:

void foo(int, int .b=1, int .c=2);
foo(5, .c=7);

Here, the compiler needs to know that, as soon as it sees a named
argument, it should consider all calls that match the argument list up
to that point *and* at some following point have an argument named `c`.
(And have defaulted arguments for whatever doesn't match up.)

IOW, what an implementation would do is:

- Start with all possible overloads of `foo`.
- Throw out any that can't match `foo(int, ...)`
- Look for one that has a named argument (with ordinal > 0) named `c`.
- Repeat for any more named arguments.
- Throw out anything that's left for which any "unbound" arguments do
not have defaults.
- Emit a call to the resulting function (if exactly one) or issue a
diagnostic.

At no point do we actually generate additional function prototypes.
Post by Jake Arkinstall
So unless I'm missing something (which is likely, this stuff isn't my
forte), allowing skipping (and/or reordering) just for these will require a
language change at a later translation phase. And in a later translation
phase, the strong type approach seems rather pointless - it could just be
done directly by the compiler, however the compiler wants to do it.
Ah, yes, I think I see. There is no *practical* reason why the logic I
outline above couldn't be applied to unnamed arguments also. That's more
a matter of "for sanity".

The main use for strong typing, at least in my current vision, is for
forwarding. (And maybe mangling.) In that sense, I think we agree.

For example, I can do this:

void bar(int .x); // #1
void bar(int .y); // #2

template <typename Args...>
void foo(Args... args)
{
bar(args...);
}

// okay, instantiates foo<arg<int, "y"_lit>> which calls #2
foo(.y=1);
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/3f8327d3-dce0-2d2a-54ba-f4c70101c49b%40gmail.com.
Cleiton Santoia
2018-08-17 18:56:34 UTC
Permalink
Some time ago I "proposed" something about this in other std thread.

My idea was just change 2 things in lambdas:

1 - Allow the lambda members to be public;
2 - Allow the '{}' to be optional in lambda definition;

So this will be a valid:
template < RectLeftTop Rect > // Concept RectLeftTop
void draw_rect(const Rect& r){
... // this uses r.left and r.top
}

template < RectX1Y1 Rect > // Concept RectX1Y1
void draw_rect(const Rect& r){
... // this overload uses r.x1 and r.y1
}

void test() {
auto x = 10;
auto lambda = [top=x, left=100, width=x+30, height=100]; // lambda
declaration without '{}'
lambda.top = lambda.top * 2; // using public members from lambda
draw_rect(lambda);
draw_rect([x1=x, x2=x+90, y1=30, y2=100]); // Use directly a lambda
}
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/cc6a4e73-cdaf-493e-80f0-73e2d2711833%40isocpp.org.
Thiago Macieira
2018-08-16 19:50:33 UTC
Permalink
Post by David Brown
Post by Matthew Woehlke
void bar(int :a);
void bar(int :x); // distinct overload
...is pointless.
I disagree. Distinct overloads like this would be nice, but (as I
wrote) extremely costly in terms of changes to implementations and
existing software. I would rather see that as a later enhancement once
we have the simple named parameters in place - my proposal does not
conflict with having this as a later feature.
I don't think you can have this as a later feature. It needs to be designed in
from the first version.

The mangling of "void bar(int)" is
_Z3bari
?bar@@***@Z

If this is used for "void bar(int :a)", then you CANNOT later overload with
"void bar(int :x)". In other words, for named arguments to be overloadable at
any point in the future, they must have been overloadable at all points in the
past too.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/1708615.QdClGnisbJ%40tjmaciei-mobl1.
David Brown
2018-08-17 11:10:44 UTC
Permalink
Post by Thiago Macieira
Post by David Brown
Post by Matthew Woehlke
void bar(int :a);
void bar(int :x); // distinct overload
...is pointless.
I disagree. Distinct overloads like this would be nice, but (as I
wrote) extremely costly in terms of changes to implementations and
existing software. I would rather see that as a later enhancement once
we have the simple named parameters in place - my proposal does not
conflict with having this as a later feature.
I don't think you can have this as a later feature. It needs to be designed in
from the first version.
The mangling of "void bar(int)" is
_Z3bari
If this is used for "void bar(int :a)", then you CANNOT later overload with
"void bar(int :x)". In other words, for named arguments to be overloadable at
any point in the future, they must have been overloadable at all points in the
past too.
Of course. And that is /fine/.

If you want to have two functions that are overloaded on the basis of
their parameter names, then you want that to be part of the definition
and declaration of /both/ functions. You don't want to have one
"normal" function and one "overloaded" function - that opens the door to
ambiguity, confusion, and getting the wrong function by mistake.

Suppose we start with named parameters in the way I described. Then you
have:

// declaration
void foo(int a, int b);

// definition can use any names, but matching names recommended
void foo(int a, int param_b) { ... }

// call
foo(1, 2);
foo(.a = 1, .b = 2);


Let's add a syntax for /required/ named parameters. Unlike someone
else's suggestion, I would want this to be clearly distinguished - not
just based on a minor change in positions. At this stage, I really
don't know what syntax would be nice here, so I'm simply going to invent
one to discuss the point - it is not a suggestion for a final choice of
syntax.

// declarations
void foo(int @a, int @b);
void foo(int @x, int @y);

// definitions must use identical names
void foo(int @a, ***@b) { ... }
void foo(int @x, ***@y) { ... }

// call
foo(.a = 1, .b = 2);
foo(.y = 10, .x = 20);

foo(1, 2) // Syntax error!

As far as the caller is concerned, the syntax for non-optional named
parameters is the same as that of choosing to use optional named parameters.

If the mangled name of "void foo(int, int)" is "foo_v_i_i", then the
declarations and definitions above would mangle to "foo_v_i_i__a_b" and
"foo_v_i_i__x_y", or something on those lines. The compiler can
distinguish the declarations, it can distinguish the definitions, it can
distinguish the mangled names used for linkage. No information needs to
be added to the ABI, the object formats, or anything else other than
some extra mangling. No changes are needed on the linker, or most of
the compiler - just a straightforward change to the compiler front-end
(and debuggers trying to interpret the mangled symbols).


Thus you need a change to the mangled name of a function only if you
want to use parameter name based overload. Other uses of parameter
names are unaffected.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/pl6abh%24btq%241%40blaine.gmane.org.
Jake Arkinstall
2018-08-17 12:36:21 UTC
Permalink
Post by David Brown
Let's add a syntax for /required/ named parameters.
The named parameter topic always starts with a suggestion that named
parameters make things easier for a user to read a function call site.
That's something I'm willing to go along with for the sake of argument.

What I'm uncomfortable about is when it forcably changes how a user writes
a function call. It doesn't make things much easier to write because
memorising the parameter names is barely different to memorising the
parameter orders. For me it's purely about reading the call site. I'm all
for people using it for their ease, but I want the choice of not using it
for mine. I know I'm not going to be creating them for a long time simply
because it isn't compatible with compilers and, being a language change,
there's no way of spoofing the behaviour.

I also don't like the notion of implicitly elevating a name to a type,
which is what I see here. Perhaps it's the physicist in me, but for me a
function operates on some types Ts..., which it is able to label purely for
its own purposes. I'm comfortable with the idea that if two calls do two
different things with the same types, either it isnt the same function or
they aren't the same semantic types. In most cases the latter should be the
case.

At least python handles the overloading issue - by not supporting
overloading. But that also comes with its own problems - it encourages
ridiculous interfaces. See pandas.to_csv as a good example - credit to them
for making such an incredible library, but their many-optional-parameter
interfaces combined with their inconsistent parameter naming styles results
in a usability nightmare, and we're opening ourselves up to that mentality
with the very mention of named parameters.

Anyway, rant over.

While I disagree with the reason for wanting forcably named parameters, one
thing it does provide is an implementation via strong types. One that can
be implemented at a higher level without changing the mangling, and without
runtime overhead. If a function has a forced named parameter, such as
my_func(@T x), that @T can be internally represented as a struct my_func_x
{ T value; }. When you call my_func(x: 3), it puts 3 into a struct
my_func_x, passes that to my_func, which then automatically
reinterpret_casts the my_func_x as a T* and dereferences into x. As
my_func_y cant implicitly cast to my_func_x, there's no ambiguity.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAC%2B0CCMrBHUr50WNJsJxhbCg7qQ%3DP%3DkG_OCniy%2BAuATdWF6Whg%40mail.gmail.com.
David Brown
2018-08-17 14:21:45 UTC
Permalink
Post by David Brown
Let's add a syntax for /required/ named parameters.
The named parameter topic always starts with a suggestion that named
parameters make things easier for a user to read a function call site.
That's something I'm willing to go along with for the sake of argument.
No one (I hope) suggests that named parameters always make it easier to
read or write function calls correctly - merely that they are a tool
that can improve readability and help get correct code in some cases.
Post by David Brown
What I'm uncomfortable about is when it forcably changes how a user
writes a function call.
I agree. I want it to be optional. I can only see it be /required/ if
parameter name based overloading is used. (Overloading by parameter
name is not something I see as a big issue, or a big use case, but some
people are keen on it.)
Post by David Brown
It doesn't make things much easier to write
because memorising the parameter names is barely different to memorising
the parameter orders.
IDE's will help with this, but otherwise I agree.
Post by David Brown
For me it's purely about reading the call site.
I'm all for people using it for their ease, but I want the choice of not
using it for mine. I know I'm not going to be creating them for a long
time simply because it isn't compatible with compilers and, being a
language change, there's no way of spoofing the behaviour.
Agreed. I would be entirely against a syntax that required changes to
the definitions or declarations of functions that made them incompatible
with existing compilers - except where it supports a new feature that
was not available previously. (This would be parameter name based
overloading.)
Post by David Brown
I also don't like the notion of implicitly elevating a name to a type,
which is what I see here. Perhaps it's the physicist in me, but for me a
function operates on some types Ts..., which it is able to label purely
for its own purposes. I'm comfortable with the idea that if two calls do
two different things with the same types, either it isnt the same
function or they aren't the same semantic types. In most cases the
latter should be the case.
At least python handles the overloading issue - by not supporting
overloading. But that also comes with its own problems - it encourages
ridiculous interfaces. See pandas.to_csv as a good example - credit to
them for making such an incredible library, but their
many-optional-parameter interfaces combined with their inconsistent
parameter naming styles results in a usability nightmare, and we're
opening ourselves up to that mentality with the very mention of named
parameters.
Anyway, rant over.
While I disagree with the reason for wanting forcably named parameters,
one thing it does provide is an implementation via strong types. One
that can be implemented at a higher level without changing the mangling,
and without runtime overhead. If a function has a forced named
as a struct my_func_x { T value; }. When you call my_func(x: 3), it puts
3 into a struct my_func_x, passes that to my_func, which then
automatically reinterpret_casts the my_func_x as a T* and dereferences
into x. As my_func_y cant implicitly cast to my_func_x, there's no
ambiguity.
What you are suggesting here, I think, is that forced named parameters -
as required for parameter name based overloading - could be handled as
syntactic sugar for generating new types on the fly. That does not
sound unreasonable, and could be a way to implement it using a minimum
of changes to existing tools.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/pl6lhm%24alv%241%40blaine.gmane.org.
Matthew Woehlke
2018-08-17 15:25:59 UTC
Permalink
Post by Jake Arkinstall
At least python handles the overloading issue - by not supporting
overloading. But that also comes with its own problems - it encourages
ridiculous interfaces. See pandas.to_csv as a good example - credit to them
for making such an incredible library, but their many-optional-parameter
interfaces combined with their inconsistent parameter naming styles results
in a usability nightmare, and we're opening ourselves up to that mentality
with the very mention of named parameters.
A Python developer would say, "thank God we don't have those awful C++
interfaces with their dozens of confusing and redundant overloads". And
there is truth to that. I've written such interfaces, and there are
absolutely times I would *much* rather have a Pythonic interface with a
great big bag of *named* parameters.

Happiness, I think, lies somewhere between the two extremes, and/or in
being able to choose the most appropriate approach for any given problem
(i.e. having both tools in our toolbox).
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/8d483389-c58d-3045-716b-998783c17b66%40gmail.com.
Vicente J. Botet Escriba
2018-08-17 14:46:42 UTC
Permalink
Post by Thiago Macieira
Post by David Brown
Post by Matthew Woehlke
void bar(int :a);
void bar(int :x); // distinct overload
...is pointless.
I disagree. Distinct overloads like this would be nice, but (as I
wrote) extremely costly in terms of changes to implementations and
existing software. I would rather see that as a later enhancement once
we have the simple named parameters in place - my proposal does not
conflict with having this as a later feature.
I don't think you can have this as a later feature. It needs to be designed in
from the first version.
The mangling of "void bar(int)" is
_Z3bari
If this is used for "void bar(int :a)", then you CANNOT later overload with
"void bar(int :x)". In other words, for named arguments to be overloadable at
any point in the future, they must have been overloadable at all points in the
past too.
I think that these are orthogonal features and should be defined
independently.

For me named parameters are just syntactic sugar and shouldn't change
neither the signature of the function nor the mangling.

For me, having two declarations of the same function with different
parameters, should just allow to use those parameters as named parameters.

So having

    void f(int a, int b);

    void f(int x, int y);

would allow to use the named parameters and b and x and y respectively.

The question is why allowing that?

The idea is that we want to avoid a successful TU to be modified because
we add an additional declaration on one of the header files.


As this would request to compiler to store somewhere all the
declarations of a specific function, I believe that in order to don't
pay for what we don't use, we would need to opt in for the feature is
some specific way, that I don't worry about. E.g.

    void f(a:int, b:int);

    void f(x:int x, y:int);

Only in this case the named parameters should be allowed.

I could live also having the naming by default, but I believe that the
name used for something that today is not in the public interface would
very often be not the most appropriated hence the need to opt in.

We should note that if opt in is not retained, this doesn't mean that
from the standard library point of view we shouldn't opt in to have a
public parameter name, as it shall be part of the wording, so bikesheing
will not be avoided.


The other alternatives for me are

* names are part of the signature and we can overload on them. This is
something else for me (this would be syntactic sugar for tag
dispatching). I'm not saying we don't need something like that, just
that I don't want to name this or mix with  name parameters as it is
naming an overload not a parameter.

    The syntax for this kind of additional named function/constructor
overload could be different as the implications are different and maybe
the needs are also different.

    If we need something else to be able to oveload it should be
something that is on the domain of types and so syntactic sugar for tag
types. This will change the signature and of course the mangling of the
function.


* only one set of names is possible for all the TU (this need the kind
of mangling you are suggesting). I can live without this. IIRC this was
the approach that was rejected by the committee.

* only one set of names is possible for a TU. This is easy to check but
I it is not stable. Adding an additional header file would add
additional forward declaration that could break the code.


Vicente
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/60fba045-252b-486e-92e0-03c08b6d5a35%40wanadoo.fr.
Thiago Macieira
2018-08-17 15:05:16 UTC
Permalink
Post by Vicente J. Botet Escriba
As this would request to compiler to store somewhere all the
declarations of a specific function, I believe that in order to don't
pay for what we don't use, we would need to opt in for the feature is
some specific way, that I don't worry about. E.g.
void f(a:int, b:int);
void f(x:int x, y:int);
Only in this case the named parameters should be allowed.
Agreed. To me, parameter names need to be opt-in. Anything else is simply not
workable as the names have not and will continue not to be stable, so they
aren't usable by users in the first place.

But my question to you is: are those two function declarations the same
function? If they are, how do you propose we declare them so that they are
*not* the same function?
Post by Vicente J. Botet Escriba
The syntax for this kind of additional named function/constructor
overload could be different as the implications are different and maybe
the needs are also different.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/1925737.EHUJpxQoH7%40tjmaciei-mobl1.
Vicente J. Botet Escriba
2018-08-18 15:09:34 UTC
Permalink
Post by Thiago Macieira
Post by Vicente J. Botet Escriba
As this would request to compiler to store somewhere all the
declarations of a specific function, I believe that in order to don't
pay for what we don't use, we would need to opt in for the feature is
some specific way, that I don't worry about. E.g.
void f(a:int, b:int);
void f(x:int x, y:int);
Only in this case the named parameters should be allowed.
Agreed. To me, parameter names need to be opt-in. Anything else is simply not
workable as the names have not and will continue not to be stable, so they
aren't usable by users in the first place.
But my question to you is: are those two function declarations the same
function? If they are, how do you propose we declare them so that they are
*not* the same function?
Yes, they declare the same function.

If we wan to have two different overload, we would need something else,
that don't need to be a named parameter. We could use now just tag types

struct tag1 {}

struct tag2 {}


void f(tag1, a:int, b:int);

void f(tag2, x:int, y:int);

Now we can call f using the tag objects

f(tag1{}, a:=1, b:=2);
f(tag2{}, x:=1, y:=2);


and we could add any syntactic sugar that make it easier to define those tags, and make them even local to the function

void f(@tag1, a:int, b:int);

void f(@tag2, x:int, y:int);


Now we can call f using the local tags

f(@tag1, a:=1, b:=2);
f(@tag2, x:=1, y:=2);

Note that tagx is not associated to any named parameter.


Vicente
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/4df1f86f-cdee-5275-bdd1-b53f2f10bef8%40wanadoo.fr.
Jeremy Maitin-Shepard
2018-08-19 22:32:17 UTC
Permalink
We already have a form of weak named parameters readily available in the form of /*parameter_name=*/value comments in combination with the clang-tidy bugprone-argument-comment check or similar functionality in other tools.

A mechanism that only warns and doesn't support forwarding/metaprogramming does not seem to me to provide much value over what we already have.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/31183044-e1e9-401f-812a-8f2e9b610b14%40isocpp.org.
Nicol Bolas
2018-08-19 23:09:43 UTC
Permalink
Post by Jeremy Maitin-Shepard
We already have a form of weak named parameters readily available in the
form of /*parameter_name=*/value comments in combination with the
clang-tidy bugprone-argument-comment check or similar functionality in
other tools.
A mechanism that only warns and doesn't support forwarding/metaprogramming
does not seem to me to provide much value over what we already have.
And how would you propose to make "forwarding/metaprogramming" work with
weak parameters? You can draw up a couple of simplistic cases that a
compiler can peek through, but you can't come up with a coherent set of
rules that work everywhere. And when I say "rules", I don't mean English
text or "something like this"; I mean something approaching standards
wording.

The fundamental issue with forwarding is about the transmission of
information from source to destination. Strong parameter proposals transmit
information in some explicit way: maybe it's a struct with known parameters
or the names are themselves parameters or something else. Most strong
parameter proposals handle parameter names in in ways C++ already
understands.

With strong parameters, `emplace(val: 2)` compiles when `emplace(2)` does
not because of normal C++ reasons. You're instantiating two different
functions, with different sets of parameters, which therefore can have
different behaviors.

Weak named parameters are intended to be purely notation information.
Therefore, `emplace(val: 2)` must instantiate and execute the same template
as `emplace(2)` does. Since the information is not passed in a channel that
C++ currently understands, you now have to create an entirely new channel
of information, which is somehow attached to a parameter yet otherwise is
undetectable by anything that isn't the compiler. One which allows such
intermediary functions to pass such named parameters to logging or other
functions without causing a compile error.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/d8acf82e-18b5-4a35-ba08-b5c415b87c24%40isocpp.org.
Jeremy Maitin-Shepard
2018-08-20 05:11:19 UTC
Permalink
Yes, it seems to me that weak named parameters are inherently incompatible with forwarding and metaprogramming, and for that reason I'm not really in favor of a weak named parameters mechanism being standardized.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/7fb3df62-d52d-4337-aec8-baca29c37835%40isocpp.org.
Matthew Woehlke
2018-08-23 17:31:47 UTC
Permalink
Post by Nicol Bolas
Post by Jeremy Maitin-Shepard
We already have a form of weak named parameters readily available in the
form of /*parameter_name=*/value comments in combination with the
clang-tidy bugprone-argument-comment check or similar functionality in
other tools.
A mechanism that only warns and doesn't support forwarding/metaprogramming
does not seem to me to provide much value over what we already have.
And how would you propose to make "forwarding/metaprogramming" work with
weak parameters? You can draw up a couple of simplistic cases that a
compiler can peek through, but you can't come up with a coherent set of
rules that work everywhere. And when I say "rules", I don't mean English
text or "something like this"; I mean something approaching standards
wording.
I don't know about "something approaching standards wording", but where
I was headed, this:

void foo(int y);
std::invoke(foo, .x=5);

...would turn into something like:

invoke(Func *foo, arg<int, "x"> a1 = 5)
{
(*foo)(a1);
}

...which could warn about decomposing the named argument "x" into a call
that names its argument "y".

So, basically, I implement "weak" names by allowing the caller to pass a
strongly named argument to a function that takes only weak names.
Delaying the decay from strongly-named to weakly-named allows most of
the forwarding cases to work.
Post by Nicol Bolas
The fundamental issue with forwarding is about the transmission of
information from source to destination. Strong parameter proposals transmit
information in some explicit way: maybe it's a struct with known parameters
or the names are themselves parameters or something else. Most strong
parameter proposals handle parameter names in in ways C++ already
understands.
Right. In the example above, the *caller* passes a strongly-named
argument, which is forwarded as a strongly named argument. It only
"loses" the naming information when it hits a function taking a
non-template parameter that is not strongly named. At that point, the
compiler has the opportunity to issue a warning.
Post by Nicol Bolas
With strong parameters, `emplace(val: 2)` compiles when `emplace(2)` does
not because of normal C++ reasons. You're instantiating two different
functions, with different sets of parameters, which therefore can have
different behaviors.
...except that in my thinking, `emplace(2)` will auto-promote to a
strongly named argument, if that's what `emplace` wants. You only get an
error if the caller provides a strongly-named argument that the callee
does not accept.

void foo(int .x);
foo(5); // okay
foo(.x=5); // okay
foo(.y=5); // error
Post by Nicol Bolas
Weak named parameters are intended to be purely notation information.
Therefore, `emplace(val: 2)` must instantiate and execute the same template
as `emplace(2)` does. Since the information is not passed in a channel that
C++ currently understands, you now have to create an entirely new channel
of information, which is somehow attached to a parameter yet otherwise is
undetectable by anything that isn't the compiler. One which allows such
intermediary functions to pass such named parameters to logging or other
functions without causing a compile error.
It's not "undetectable". OTOH, if you have:

void foo(int x);
foo(5); // okay
foo(.x=5); // okay

...by the time you're in `foo`, you've lost the name information.
Forwarding works if you accept a template type. If you accept a concrete
type, the name is lost.
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/0d06fd00-4c66-c57c-9663-d7d967262e6b%40gmail.com.
Vicente J. Botet Escriba
2018-08-20 06:00:23 UTC
Permalink
Post by Jeremy Maitin-Shepard
We already have a form of weak named parameters readily available in the form of /*parameter_name=*/value comments in combination with the clang-tidy bugprone-argument-comment check or similar functionality in other tools.
A mechanism that only warns and doesn't support forwarding/metaprogramming does not seem to me to provide much value over what we already have.
If you find the clang tidy check is useful, the added value is that I
wouldn't need clang-tidy to check for it and we would have the feature
available with all the compliant compilers :)

I don't like these kind of comments. We could instead use attributes,
but they are too heavyweight to my taste.


Vicente
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/2cb1c0c1-ff00-6864-b8bd-d0a708b5e504%40wanadoo.fr.
Nicol Bolas
2018-08-20 16:11:25 UTC
Permalink
On Monday, August 20, 2018 at 2:00:25 AM UTC-4, Vicente J. Botet Escriba
Post by Jeremy Maitin-Shepard
We already have a form of weak named parameters readily available in the form of /*parameter_name=*/value comments in combination with the clang-tidy bugprone-argument-comment check or similar functionality in other tools.
A mechanism that only warns and doesn't support forwarding/metaprogramming does not seem to me to provide much value over what we already have.
If you find the clang tidy check is useful, the added value is that I
wouldn't need clang-tidy to check for it and we would have the feature
available with all the compliant compilers :)
I don't like these kind of comments. We could instead use attributes, but
they are too heavyweight to my taste.
I think his point (and if it's not his, then it's mine) is that, if there's
a way to just let implementations handle it outside of the language itself,
then why not just do that?

Weak named parameters are pure notation. They exist to communicate
information to the reader about what's going on. And that's all they do.

Weak named parameters do not communicate information to the implementation
for the purpose of code generation. The only interaction the implementation
has with them is to verify that the caller and callee used the same name.
They merely ensure that the reader's information is accurate.

Weak named parameters do not change how you implement your functions, not
on an API level. Since you can't overload based on weak parameters, you
can't write `rectangle(top_left: ...)` as opposed to
`rectangle(bottom_right: ...)`. You can express which convention the
function uses, but you cannot allow the caller to *select* a convention.

Compare this to concepts and contracts. Concepts change what the language
is doing. When you constrain a template, that *does something* to the
template. It changes how code is generated (or more specifically, when it
is not generated).

Contracts seem like notation, but they're not. Why? Pre-contracts,
exceptions were sometimes used for logic errors; we even have
`std::logic_error` as an exception base class. Once we have contracts in
place, we can take stuff like that out, turning contract violations into
actual *contract violations*.

Contracts change how you write code (or rather, make it easier for you to
write code the way you should have been writing it). They allow you to
specify a different kind of meaning in the language, compared to what you
could have before.

Weak parameters change neither of these. There are very few C++ language
features (outside of certain attributes) like this.

Given this fact, why should the committee spend time on something that is
purely rotational? Don't they have more useful things to be getting on with?
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/5315cec3-6d25-4c92-b31b-e5dcd5d8f68c%40isocpp.org.
Vicente J. Botet Escriba
2018-08-20 06:15:01 UTC
Permalink
On Sunday, August 19, 2018 at 5:21:11 PM UTC-4, Vicente J. Botet
On Sunday, August 19, 2018 at 7:46:58 PM UTC+3, Vicente J. Botet
On Sunday, August 19, 2018 at 3:26:12 PM UTC+3, Vicente J.
Independently of the language feature, using a tag type
allows to
transport the tag between different functions. In
addition, you cannot
change the class constructor name, so you will need a
tag to be able to
overload it. Take for example the in_place_t tag.
https://groups.google.com/a/isocpp.org/d/msg/std-proposals/tPtdQE2GXb0/4OjT5Z4pBQAJ
<https://groups.google.com/a/isocpp.org/d/msg/std-proposals/tPtdQE2GXb0/4OjT5Z4pBQAJ>
Feel free to comment there, I am undecided on the topic.
I'm not sure yet we need some syntactic sugar for this tag
dispatching feature neither.
I'm just trying to separate the named parameter part from the
overload part as orthogonal features.
You go too far for my taste in your proposal and you propose
to have all at once. I'll be against such a feature.
Can you elaborate a bit more, what are your expectations and
where should a line be drawn? As you can see in the comments to
the post, there are similar concerns.
In any case it is not a proposal, but an investigation. It is
clear tags have overlap with strong names, and if we can get an
attractive proposition, based on tags, we can mark at least one
part (the harder part?) of the named arguments equation "fixed".
I would like to see the two features proposed independently.
I see more added value for weak named parameters that are optional
and opt in on the author side (as the workarounds are not always
friendly) than the strong named parameters that can be used to
overload function or constructors and that are not optional (as
tag types are an almost friendly library solution, as the standard
library has showed already multiple times).
The problem with having them be independent is that they're /not/
independent. They're both playing around in the same space: invoking a
parameter's name when you call the function.
The first question any named parameter proposal has to answer is
whether to rely on the existing parameter name infrastructure or to
use a special way to define them. There are arguments for both weak
and strong parameters to want to have syntax to declare named
parameters on a function. This is because, by having users rely on
them to some degree (even if mis-matched naming is just a warning),
you are making those parameter names part of the interface of the API.
And that's different from how parameter names have been treated in the
past.
I'm not for strong named parameters. For me, this is a disguised form of
mixing weak named parameters and tag dispatching. This is why I believe
the features are independent.
Now you can put them together and obtain named parameters and tag dispatch.
If you try to develop weak and strong parameters completely
independently, then what you can end up with are two proposals that
provide completely different ways of declaring such parameters. And
considering all of the stuff that we keep cramming into function
declarations these days, giving parameters /three names/ is utterly
absurd. Even if you forbid weak parameter names on functions with
strong names, that's still 3 separate syntaxes for declaring parameter
names.
If we want weak and strong named parameters and don't see another
solution than having two syntaxes :(

I don't believe that we want non op in named parametrs, so each one of
the weak/strong alternatives would need a specific syntax.
So I don't think it's reasonable to develop the two proposals
completely independently from one another. They should at least be
developed with the knowledge that the other is a possibility, and with
syntax that can reasonably fit together.
Maybe you are right, but I would like that the proposal are clearly
separated, so that we can be agains one from or the other.
Lastly, it should be noted that tagged dispatch doesn't help with what
I will refer to as "mega-functions": functions that take stupidly
large numbers of relatively independent parameters, but for some
reason don't want to take them as a convenient aggregate. This is a
use case that some people want to support, to avoid conceptual
two-stage construction.
IMHO, this case is covered by weak named parameters already.
If you accept that your signature changes and require that the argument
must be named, strong named parameters could as well cover it.

If you don't accept that your signature changes and require that the
argument must be named, weak named parameters + some static analysis
tool (as clang-tidy) help could as well cover it (but not that the
syantax will be already defined by the standard).

Maybe we need strong named parameters that don't change the signatures
as well ;-)

Vicente
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/0d02cfac-0504-62d2-9835-b400daff972b%40wanadoo.fr.
Nicol Bolas
2018-08-20 15:37:39 UTC
Permalink
On Monday, August 20, 2018 at 2:15:17 AM UTC-4, Vicente J. Botet Escriba
On Sunday, August 19, 2018 at 5:21:11 PM UTC-4, Vicente J. Botet Escriba
On Sunday, August 19, 2018 at 7:46:58 PM UTC+3, Vicente J. Botet Escriba
On Sunday, August 19, 2018 at 3:26:12 PM UTC+3, Vicente J. Botet Escriba
Independently of the language feature, using a tag type allows to
transport the tag between different functions. In addition, you cannot
change the class constructor name, so you will need a tag to be able to
overload it. Take for example the in_place_t tag.
https://groups.google.com/a/isocpp.org/d/msg/std-proposals/tPtdQE2GXb0/4OjT5Z4pBQAJ
Feel free to comment there, I am undecided on the topic.
I'm not sure yet we need some syntactic sugar for this tag dispatching
feature neither.
I'm just trying to separate the named parameter part from the overload
part as orthogonal features.
You go too far for my taste in your proposal and you propose to have all
at once. I'll be against such a feature.
Can you elaborate a bit more, what are your expectations and where should
a line be drawn? As you can see in the comments to the post, there are
similar concerns.
In any case it is not a proposal, but an investigation. It is clear tags
have overlap with strong names, and if we can get an attractive
proposition, based on tags, we can mark at least one part (the harder
part?) of the named arguments equation "fixed".
I would like to see the two features proposed independently.
I see more added value for weak named parameters that are optional and
opt in on the author side (as the workarounds are not always friendly) than
the strong named parameters that can be used to overload function or
constructors and that are not optional (as tag types are an almost friendly
library solution, as the standard library has showed already multiple
times).
The problem with having them be independent is that they're *not*
independent. They're both playing around in the same space: invoking a
parameter's name when you call the function.
The first question any named parameter proposal has to answer is whether
to rely on the existing parameter name infrastructure or to use a special
way to define them. There are arguments for both weak and strong parameters
to want to have syntax to declare named parameters on a function. This is
because, by having users rely on them to some degree (even if mis-matched
naming is just a warning), you are making those parameter names part of the
interface of the API. And that's different from how parameter names have
been treated in the past.
I'm not for strong named parameters. For me, this is a disguised form of
mixing weak named parameters and tag dispatching. This is why I believe the
features are independent.
Now you can put them together and obtain named parameters and tag dispatch.
If you try to develop weak and strong parameters completely independently,
then what you can end up with are two proposals that provide completely
different ways of declaring such parameters. And considering all of the
stuff that we keep cramming into function declarations these days, giving
parameters *three names* is utterly absurd. Even if you forbid weak
parameter names on functions with strong names, that's still 3 separate
syntaxes for declaring parameter names.
If we want weak and strong named parameters and don't see another solution
than having two syntaxes :(
If that's the case, then we shouldn't have weak named parameters at all.
Remember: weak named parameters are purely notational; they catch errors.
That makes them a "nice to have". Strong named parameters provide genuine
functionality, allowing you to express things that could not be expressed
before.

If the design space is sufficiently constrained to only permit one or the
other, then it should be the one that actually does something.

I don't believe that we want non op in named parametrs, so each one of the
weak/strong alternatives would need a specific syntax.
So I don't think it's reasonable to develop the two proposals completely
independently from one another. They should at least be developed with the
knowledge that the other is a possibility, and with syntax that can
reasonably fit together.
Maybe you are right, but I would like that the proposal are clearly
separated, so that we can be agains one from or the other.
So, you can't be against one part of a proposal? The standards committee
does it all the time.
Lastly, it should be noted that tagged dispatch doesn't help with what I
will refer to as "mega-functions": functions that take stupidly large
numbers of relatively independent parameters, but for some reason don't
want to take them as a convenient aggregate. This is a use case that some
people want to support, to avoid conceptual two-stage construction.
IMHO, this case is covered by weak named parameters already.
Then perhaps you're not understanding what a "mega-function" is. We're
talking about functions with *dozens* of parameters, most of which are
optional. Consider all of the various parameters you deal with when setting
up a window. Window styles, size, position, hierarchy, font choice, and
other things. Each of those are conceptually one or more parameters to the
window creation function.

"Ideally", these would be literal parameters to a hypothetical Window
class's constructor. But they're not; most such classes give relatively
limited numbers of parameters to the Window's constructor. The rest are
values set after the Window's construction, which means that defaults are
used until those get set. Basically, it's two-stage construction.

The only way you can get the "ideal" case is if order for parameters is *completely
removed* for such functions. You can specify the arguments in any order
when you call them, and the caller can default any parameter with a default
value simply by not specifying it.

Weak named parameters can't do that. Tag dispatch can't do that (not
without extraordinary pain on the callee side). Even designated
initializers have to be specified in the right order.

If you accept that your signature changes and require that the argument
must be named, strong named parameters could as well cover it.
If you don't accept that your signature changes and require that the
argument must be named, weak named parameters + some static analysis tool
(as clang-tidy) help could as well cover it (but not that the syantax will
be already defined by the standard).
Maybe we need strong named parameters that don't change the signatures as
well ;-)
Vicente
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/9f3550db-0cce-4259-85ef-428d8cfba63c%40isocpp.org.
m***@gmail.com
2018-08-20 16:20:20 UTC
Permalink
Post by Nicol Bolas
On Monday, August 20, 2018 at 2:15:17 AM UTC-4, Vicente J. Botet Escriba
On Sunday, August 19, 2018 at 5:21:11 PM UTC-4, Vicente J. Botet Escriba
On Sunday, August 19, 2018 at 7:46:58 PM UTC+3, Vicente J. Botet Escriba
On Sunday, August 19, 2018 at 3:26:12 PM UTC+3, Vicente J. Botet
Independently of the language feature, using a tag type allows to
transport the tag between different functions. In addition, you cannot
change the class constructor name, so you will need a tag to be able to
overload it. Take for example the in_place_t tag.
https://groups.google.com/a/isocpp.org/d/msg/std-proposals/tPtdQE2GXb0/4OjT5Z4pBQAJ
Feel free to comment there, I am undecided on the topic.
I'm not sure yet we need some syntactic sugar for this tag dispatching
feature neither.
I'm just trying to separate the named parameter part from the overload
part as orthogonal features.
You go too far for my taste in your proposal and you propose to have
all at once. I'll be against such a feature.
Can you elaborate a bit more, what are your expectations and where
should a line be drawn? As you can see in the comments to the post, there
are similar concerns.
In any case it is not a proposal, but an investigation. It is clear
tags have overlap with strong names, and if we can get an attractive
proposition, based on tags, we can mark at least one part (the harder
part?) of the named arguments equation "fixed".
I would like to see the two features proposed independently.
I see more added value for weak named parameters that are optional and
opt in on the author side (as the workarounds are not always friendly) than
the strong named parameters that can be used to overload function or
constructors and that are not optional (as tag types are an almost friendly
library solution, as the standard library has showed already multiple
times).
The problem with having them be independent is that they're *not*
independent. They're both playing around in the same space: invoking a
parameter's name when you call the function.
The first question any named parameter proposal has to answer is whether
to rely on the existing parameter name infrastructure or to use a special
way to define them. There are arguments for both weak and strong parameters
to want to have syntax to declare named parameters on a function. This is
because, by having users rely on them to some degree (even if mis-matched
naming is just a warning), you are making those parameter names part of the
interface of the API. And that's different from how parameter names have
been treated in the past.
I'm not for strong named parameters. For me, this is a disguised form of
mixing weak named parameters and tag dispatching. This is why I believe the
features are independent.
Now you can put them together and obtain named parameters and tag dispatch.
If you try to develop weak and strong parameters completely
independently, then what you can end up with are two proposals that provide
completely different ways of declaring such parameters. And considering all
of the stuff that we keep cramming into function declarations these days,
giving parameters *three names* is utterly absurd. Even if you forbid
weak parameter names on functions with strong names, that's still 3
separate syntaxes for declaring parameter names.
If we want weak and strong named parameters and don't see another
solution than having two syntaxes :(
If that's the case, then we shouldn't have weak named parameters at all.
Remember: weak named parameters are purely notational; they catch errors.
That makes them a "nice to have". Strong named parameters provide genuine
functionality, allowing you to express things that could not be expressed
before.
If the design space is sufficiently constrained to only permit one or the
other, then it should be the one that actually does something.
I don't believe that we want non op in named parametrs, so each one of the
weak/strong alternatives would need a specific syntax.
So I don't think it's reasonable to develop the two proposals completely
independently from one another. They should at least be developed with the
knowledge that the other is a possibility, and with syntax that can
reasonably fit together.
Maybe you are right, but I would like that the proposal are clearly
separated, so that we can be agains one from or the other.
So, you can't be against one part of a proposal? The standards committee
does it all the time.
Lastly, it should be noted that tagged dispatch doesn't help with what I
will refer to as "mega-functions": functions that take stupidly large
numbers of relatively independent parameters, but for some reason don't
want to take them as a convenient aggregate. This is a use case that some
people want to support, to avoid conceptual two-stage construction.
IMHO, this case is covered by weak named parameters already.
Then perhaps you're not understanding what a "mega-function" is. We're
talking about functions with *dozens* of parameters, most of which are
optional. Consider all of the various parameters you deal with when setting
up a window. Window styles, size, position, hierarchy, font choice, and
other things. Each of those are conceptually one or more parameters to the
window creation function.
"Ideally", these would be literal parameters to a hypothetical Window
class's constructor. But they're not; most such classes give relatively
limited numbers of parameters to the Window's constructor. The rest are
values set after the Window's construction, which means that defaults are
used until those get set. Basically, it's two-stage construction.
The only way you can get the "ideal" case is if order for parameters is *completely
removed* for such functions. You can specify the arguments in any order
when you call them, and the caller can default any parameter with a default
value simply by not specifying it.
Weak named parameters can't do that. Tag dispatch can't do that (not
without extraordinary pain on the callee side). Even designated
initializers have to be specified in the right order.
Are sure about that? Argument rearrangement is doable without changing the
signature (a.k.a. strong)

Where do you think it will fail?
Post by Nicol Bolas
If you accept that your signature changes and require that the argument
must be named, strong named parameters could as well cover it.
If you don't accept that your signature changes and require that the
argument must be named, weak named parameters + some static analysis tool
(as clang-tidy) help could as well cover it (but not that the syantax will
be already defined by the standard).
Maybe we need strong named parameters that don't change the signatures as
well ;-)
Vicente
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/89483da2-1435-49ef-94ea-d9d90fbac549%40isocpp.org.
Nicol Bolas
2018-08-20 18:45:01 UTC
Permalink
Post by m***@gmail.com
Post by Nicol Bolas
On Monday, August 20, 2018 at 2:15:17 AM UTC-4, Vicente J. Botet Escriba
On Sunday, August 19, 2018 at 5:21:11 PM UTC-4, Vicente J. Botet Escriba
On Sunday, August 19, 2018 at 7:46:58 PM UTC+3, Vicente J. Botet
On Sunday, August 19, 2018 at 3:26:12 PM UTC+3, Vicente J. Botet
Independently of the language feature, using a tag type allows to
transport the tag between different functions. In addition, you cannot
change the class constructor name, so you will need a tag to be able to
overload it. Take for example the in_place_t tag.
https://groups.google.com/a/isocpp.org/d/msg/std-proposals/tPtdQE2GXb0/4OjT5Z4pBQAJ
Feel free to comment there, I am undecided on the topic.
I'm not sure yet we need some syntactic sugar for this tag dispatching
feature neither.
I'm just trying to separate the named parameter part from the overload
part as orthogonal features.
You go too far for my taste in your proposal and you propose to have
all at once. I'll be against such a feature.
Can you elaborate a bit more, what are your expectations and where
should a line be drawn? As you can see in the comments to the post, there
are similar concerns.
In any case it is not a proposal, but an investigation. It is clear
tags have overlap with strong names, and if we can get an attractive
proposition, based on tags, we can mark at least one part (the harder
part?) of the named arguments equation "fixed".
I would like to see the two features proposed independently.
I see more added value for weak named parameters that are optional and
opt in on the author side (as the workarounds are not always friendly) than
the strong named parameters that can be used to overload function or
constructors and that are not optional (as tag types are an almost friendly
library solution, as the standard library has showed already multiple
times).
The problem with having them be independent is that they're *not*
independent. They're both playing around in the same space: invoking a
parameter's name when you call the function.
The first question any named parameter proposal has to answer is whether
to rely on the existing parameter name infrastructure or to use a special
way to define them. There are arguments for both weak and strong parameters
to want to have syntax to declare named parameters on a function. This is
because, by having users rely on them to some degree (even if mis-matched
naming is just a warning), you are making those parameter names part of the
interface of the API. And that's different from how parameter names have
been treated in the past.
I'm not for strong named parameters. For me, this is a disguised form of
mixing weak named parameters and tag dispatching. This is why I believe the
features are independent.
Now you can put them together and obtain named parameters and tag dispatch.
If you try to develop weak and strong parameters completely
independently, then what you can end up with are two proposals that provide
completely different ways of declaring such parameters. And considering all
of the stuff that we keep cramming into function declarations these days,
giving parameters *three names* is utterly absurd. Even if you forbid
weak parameter names on functions with strong names, that's still 3
separate syntaxes for declaring parameter names.
If we want weak and strong named parameters and don't see another
solution than having two syntaxes :(
If that's the case, then we shouldn't have weak named parameters at all.
Remember: weak named parameters are purely notational; they catch errors.
That makes them a "nice to have". Strong named parameters provide genuine
functionality, allowing you to express things that could not be expressed
before.
If the design space is sufficiently constrained to only permit one or the
other, then it should be the one that actually does something.
I don't believe that we want non op in named parametrs, so each one of
the weak/strong alternatives would need a specific syntax.
So I don't think it's reasonable to develop the two proposals completely
independently from one another. They should at least be developed with the
knowledge that the other is a possibility, and with syntax that can
reasonably fit together.
Maybe you are right, but I would like that the proposal are clearly
separated, so that we can be agains one from or the other.
So, you can't be against one part of a proposal? The standards committee
does it all the time.
Lastly, it should be noted that tagged dispatch doesn't help with what I
will refer to as "mega-functions": functions that take stupidly large
numbers of relatively independent parameters, but for some reason don't
want to take them as a convenient aggregate. This is a use case that some
people want to support, to avoid conceptual two-stage construction.
IMHO, this case is covered by weak named parameters already.
Then perhaps you're not understanding what a "mega-function" is. We're
talking about functions with *dozens* of parameters, most of which are
optional. Consider all of the various parameters you deal with when setting
up a window. Window styles, size, position, hierarchy, font choice, and
other things. Each of those are conceptually one or more parameters to the
window creation function.
"Ideally", these would be literal parameters to a hypothetical Window
class's constructor. But they're not; most such classes give relatively
limited numbers of parameters to the Window's constructor. The rest are
values set after the Window's construction, which means that defaults are
used until those get set. Basically, it's two-stage construction.
The only way you can get the "ideal" case is if order for parameters is *completely
removed* for such functions. You can specify the arguments in any order
when you call them, and the caller can default any parameter with a default
value simply by not specifying it.
Weak named parameters can't do that. Tag dispatch can't do that (not
without extraordinary pain on the callee side). Even designated
initializers have to be specified in the right order.
Are sure about that? Argument rearrangement is doable without changing the
signature (a.k.a. strong)
Maybe we have very different ideas about what "strong named parameters"
means. The question of "changing the signature" is not the distinction
between "strong" and "weak". At least, it's not the distinction that I'm
talking about it.

"Weak named parameters" to me refers to named parameters which are all of
the following:

1. Optional. You can call a function that has named parameters without
naming the parameter(s) at the call site.
2. Ordered. The order of the arguments must match the parameter order of
the function, regardless of the names you specify at the call site.
3. Overload-neutral. The presence or absence of names at the call site has
no effect on function overloading.

Essentially, if your rules require that all named parameter function calls
will invoke the same function with the same behavior if you stripped out
all of the names, then the named parameter proposal is "weak".

Any named parameter feature which imposes rules antithetical to at least
one of the above is "strong". With the strongest being the antithesis to
all of them.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/333693b1-38a8-424f-bc15-0b36131b97f4%40isocpp.org.
Hyman Rosen
2018-08-20 19:29:13 UTC
Permalink
Post by Nicol Bolas
"Weak named parameters" to me refers to named parameters which are all of
1. Optional. You can call a function that has named parameters without
naming the parameter(s) at the call site.
2. Ordered. The order of the arguments must match the parameter order of
the function, regardless of the names you specify at the call site.
3. Overload-neutral. The presence or absence of names at the call site has
no effect on function overloading.
Essentially, if your rules require that all named parameter function calls
will invoke the same function with the same behavior if you stripped out
all of the names, then the named parameter proposal is "weak".
Any named parameter feature which imposes rules antithetical to at least
one of the above is "strong". With the strongest being the antithesis to
all of them.
Just for reference, Ada has
1. Optional/Mixed: You may call a function with a number of leading
positional arguments followed by named ones:
my_proc(1, 2, 3, foo => 7, bar => 9);
2. Not Ordered: named arguments can be specified in any order, after any
ordered positional ones
3. Affects Overloading: See <
https://www2.adacore.com/gap-static/GNAT_Book/html/node10.htm>

Ada has the caveat that "... operations that only differ in the names of
the formal parameters,
but not their types, cannot be visible at the same point: either one hides
the other through
scope and visibility rules, or else the declarations are illegal."
However, you can still have

*function* F(A: Integer, B: Integer := 0) *return* Integer;
*function* F(C: Integer ) *return* Integer;

and the call f(5) will be ambiguous, while the call f(C => 5) will call the
second function.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAHSYqdaHoEKckA5Mg9QQGG2J0AnvmDTaPHTuo-CpMZ5Wwp3omw%40mail.gmail.com.
m***@gmail.com
2018-08-20 20:18:34 UTC
Permalink
Post by m***@gmail.com
Post by m***@gmail.com
Post by Nicol Bolas
On Monday, August 20, 2018 at 2:15:17 AM UTC-4, Vicente J. Botet Escriba
On Sunday, August 19, 2018 at 5:21:11 PM UTC-4, Vicente J. Botet
On Sunday, August 19, 2018 at 7:46:58 PM UTC+3, Vicente J. Botet
On Sunday, August 19, 2018 at 3:26:12 PM UTC+3, Vicente J. Botet
Independently of the language feature, using a tag type allows to
transport the tag between different functions. In addition, you cannot
change the class constructor name, so you will need a tag to be able to
overload it. Take for example the in_place_t tag.
https://groups.google.com/a/isocpp.org/d/msg/std-proposals/tPtdQE2GXb0/4OjT5Z4pBQAJ
Feel free to comment there, I am undecided on the topic.
I'm not sure yet we need some syntactic sugar for this tag
dispatching feature neither.
I'm just trying to separate the named parameter part from the
overload part as orthogonal features.
You go too far for my taste in your proposal and you propose to have
all at once. I'll be against such a feature.
...
Lastly, it should be noted that tagged dispatch doesn't help with what
I will refer to as "mega-functions": functions that take stupidly large
numbers of relatively independent parameters, but for some reason don't
want to take them as a convenient aggregate. This is a use case that some
people want to support, to avoid conceptual two-stage construction.
IMHO, this case is covered by weak named parameters already.
Then perhaps you're not understanding what a "mega-function" is. We're
talking about functions with *dozens* of parameters, most of which are
optional. Consider all of the various parameters you deal with when setting
up a window. Window styles, size, position, hierarchy, font choice, and
other things. Each of those are conceptually one or more parameters to the
window creation function.
"Ideally", these would be literal parameters to a hypothetical Window
class's constructor. But they're not; most such classes give relatively
limited numbers of parameters to the Window's constructor. The rest are
values set after the Window's construction, which means that defaults are
used until those get set. Basically, it's two-stage construction.
The only way you can get the "ideal" case is if order for parameters is *completely
removed* for such functions. You can specify the arguments in any order
when you call them, and the caller can default any parameter with a default
value simply by not specifying it.
Weak named parameters can't do that. Tag dispatch can't do that (not
without extraordinary pain on the callee side). Even designated
initializers have to be specified in the right order.
Are sure about that? Argument rearrangement is doable without changing the
Post by m***@gmail.com
signature (a.k.a. strong)
Maybe we have very different ideas about what "strong named parameters"
means. The question of "changing the signature" is not the distinction
between "strong" and "weak". At least, it's not the distinction that I'm
talking about it.
"Weak named parameters" to me refers to named parameters which are all of
1. Optional. You can call a function that has named parameters without
naming the parameter(s) at the call site.
2. Ordered. The order of the arguments must match the parameter order of
the function, regardless of the names you specify at the call site.
3. Overload-neutral. The presence or absence of names at the call site has
no effect on function overloading.
Essentially, if your rules require that all named parameter function calls
will invoke the same function with the same behavior if you stripped out
all of the names, then the named parameter proposal is "weak".
Any named parameter feature which imposes rules antithetical to at least
one of the above is "strong". With the strongest being the antithesis to
all of them.
I see, for you weak refers to the notion the call is the same, but
unchecked, without them.

For me strong is referring to "does it introduce a new signature", the same
way strong typedef introduces a new type. Everything else is weak as it is
about the compiler not the code.

Changing the signature is a clear boundary in both semantics and
implementation.

But in the realm of non-changing-the-signature names, a lot can be done,
granted the calls *will* differ w/ and w/o names.
Should it be done is a different matter, this is a debate as heated as the
one about signature - some people consider names useless if they don't
rearrange/skip defaults, some are happy with just checking alone.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/a9c81a6a-3fdb-41c3-afee-9e5041f6815f%40isocpp.org.
Nicol Bolas
2018-08-21 01:52:56 UTC
Permalink
Post by m***@gmail.com
Post by Nicol Bolas
Post by m***@gmail.com
Are sure about that? Argument rearrangement is doable without changing
the signature (a.k.a. strong)
Maybe we have very different ideas about what "strong named parameters"
means. The question of "changing the signature" is not the distinction
between "strong" and "weak". At least, it's not the distinction that I'm
talking about it.
"Weak named parameters" to me refers to named parameters which are all of
1. Optional. You can call a function that has named parameters without
naming the parameter(s) at the call site.
2. Ordered. The order of the arguments must match the parameter order of
the function, regardless of the names you specify at the call site.
3. Overload-neutral. The presence or absence of names at the call site
has no effect on function overloading.
Essentially, if your rules require that all named parameter function
calls will invoke the same function with the same behavior if you stripped
out all of the names, then the named parameter proposal is "weak".
Any named parameter feature which imposes rules antithetical to at least
one of the above is "strong". With the strongest being the antithesis to
all of them.
I see, for you weak refers to the notion the call is the same, but
unchecked, without them.
For me strong is referring to "does it introduce a new signature", the
same way strong typedef introduces a new type. Everything else is weak as
it is about the compiler not the code.
That's not what you said earlier
<https://groups.google.com/a/isocpp.org/d/msg/std-proposals/MbDT0vsA2j0/1VPQM7AsAAAJ>
:

Also, this obviously does not address the named arguments, *that are
Post by m***@gmail.com
optional, the "weak" ones*, so this solution will not make everyone
happy.
Emphasis added. And there's this post
<https://groups.google.com/a/isocpp.org/d/msg/std-proposals/MbDT0vsA2j0/uWG77JxeDQAJ>
:

//weak argument names, not mandatory
...
//strong argument name, adds an overload, not ignorable
Yes, that post is talking about how you would declare weak names
differently from strong names, but it's also talking about how they get
used at the call site: "not mandatory" vs. "not ignorable".

Changing the signature is a clear boundary in both semantics and
Post by m***@gmail.com
implementation.
But in the realm of non-changing-the-signature names, a lot can be done,
Post by m***@gmail.com
granted the calls *will* differ w/ and w/o names.
I think you're too focused on signature as the notion of a function's
identity. There are aspects of functions which are not their signature yet
directly relate to its identity.

Return values. If you declare two functions with the same name and
signatures with different return values, then you get a compile error.
`noexcept` works that way too; you can't be inconsistent about that. Both
of these are part of the function's type, but not its signature (though
`noexcept` can be cast away).

Contracts affect neither type nor signature, but even that requires some
basic consistency. You can declare contracts on a function or not. But all
contract declarations for the same function must be consistent.

If a parameter name can be used as a syntactic modifier when calling the
function (for the purposes of this discussion, anything which affects
actual code generation. This includes reordering of arguments), then that
name ought to be, if not part of the function's type, then at least have as
much consistency as its contracts. That is, if you want to be able to
reorder parameters, then the function should consistently assign each
parameter a single name or a single "unnamed".

If names can be inconsistent and still affect syntax, bad things result.

Should it be done is a different matter, this is a debate as heated as the
Post by m***@gmail.com
one about signature - some people consider names useless if they don't
rearrange/skip defaults, some are happy with just checking alone.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/371d2665-ee4b-4599-9d83-1d271312c5a8%40isocpp.org.
m***@gmail.com
2018-08-21 08:04:26 UTC
Permalink
Post by Nicol Bolas
Post by m***@gmail.com
Post by Nicol Bolas
Post by m***@gmail.com
Are sure about that? Argument rearrangement is doable without changing
the signature (a.k.a. strong)
Maybe we have very different ideas about what "strong named parameters"
means. The question of "changing the signature" is not the distinction
between "strong" and "weak". At least, it's not the distinction that I'm
talking about it.
"Weak named parameters" to me refers to named parameters which are all
1. Optional. You can call a function that has named parameters without
naming the parameter(s) at the call site.
2. Ordered. The order of the arguments must match the parameter order of
the function, regardless of the names you specify at the call site.
3. Overload-neutral. The presence or absence of names at the call site
has no effect on function overloading.
Essentially, if your rules require that all named parameter function
calls will invoke the same function with the same behavior if you stripped
out all of the names, then the named parameter proposal is "weak".
Any named parameter feature which imposes rules antithetical to at least
one of the above is "strong". With the strongest being the antithesis to
all of them.
I see, for you weak refers to the notion the call is the same, but
unchecked, without them.
For me strong is referring to "does it introduce a new signature", the
same way strong typedef introduces a new type. Everything else is weak as
it is about the compiler not the code.
That's not what you said earlier
<https://groups.google.com/a/isocpp.org/d/msg/std-proposals/MbDT0vsA2j0/1VPQM7AsAAAJ>
Also, this obviously does not address the named arguments, *that are
Post by m***@gmail.com
optional, the "weak" ones*, so this solution will not make everyone
happy.
Emphasis added. And there's this post
<https://groups.google.com/a/isocpp.org/d/msg/std-proposals/MbDT0vsA2j0/uWG77JxeDQAJ>
//weak argument names, not mandatory
...
//strong argument name, adds an overload, not ignorable
Yes, that post is talking about how you would declare weak names
differently from strong names, but it's also talking about how they get
used at the call site: "not mandatory" vs. "not ignorable".
There is no contradiction, they are optional, and ignorable by the user (he
might not use them).
Now, it depends on how much features they have, they might also be as weak
as you assume they are, so they are (can be) ignored by the compiler as
well and the call is the same.

Most of the time here we talked about these weakest ones, and considered
"extra features" as "bonuses".

For me personally strong were always the one changing the signature, that's
why the first post about tags-as-labels was called "Strong named arguments
as tag overloads"

And weak for me were not rearranging or skipping, but having
defaulted-by-naming f(a:, b:, 10)

Of course even these are not ignorable as the call will fail without them.
Probably using the word ignorable was not correct.

In any case weak names are optional.
This is not to say, they do not affect overloading, they do, but only on
the call site.

void func(int a, int b);
void func(int a, int b: b=1, int c: c=2);

func(1, 3); //< overload 1
func(1, b: 3); //< overload 2
func(1, c: 3); //< overload 2
Post by Nicol Bolas
Changing the signature is a clear boundary in both semantics and
Post by m***@gmail.com
implementation.
But in the realm of non-changing-the-signature names, a lot can be done,
Post by m***@gmail.com
granted the calls *will* differ w/ and w/o names.
I think you're too focused on signature as the notion of a function's
identity. There are aspects of functions which are not their signature yet
directly relate to its identity.
Return values. If you declare two functions with the same name and
signatures with different return values, then you get a compile error.
`noexcept` works that way too; you can't be inconsistent about that. Both
of these are part of the function's type, but not its signature (though
`noexcept` can be cast away).
Contracts affect neither type nor signature, but even that requires some
basic consistency. You can declare contracts on a function or not. But all
contract declarations for the same function must be consistent.
If a parameter name can be used as a syntactic modifier when calling the
function (for the purposes of this discussion, anything which affects
actual code generation. This includes reordering of arguments), then that
name ought to be, if not part of the function's type, then at least have as
much consistency as its contracts. That is, if you want to be able to
reorder parameters, then the function should consistently assign each
parameter a single name or a single "unnamed".
In the original post about weak arguments, I suggested they obey the rules
of default arguments - you name your arguments only in the first
declaration. No names afterwards, not even the same.

auto child(name mother: mom, name dad);

// auto child(name mother: mom, name dad); *//< error*
// auto child(name mom, name father: dad); *//< error*
auto child(name mutter, vater); *//< OK*
auto child(name mother, name father) *//< OK*
{
// implementation
}

This seems the be the most consistent approach as (weak) named arguments
ultimately inhabit *exactly* the same design space as default arguments - a
compiler helper.

With default arguments the compiler is only obligated to copy-paste the
default expression if we don't pass a value.

With names it is a matter of what features we want to have:

- to only name-check
- to paste in place of name-only
- to paste on omission
- to rearrange
Post by Nicol Bolas
If names can be inconsistent and still affect syntax, bad things result.
Should it be done is a different matter, this is a debate as heated as the
Post by m***@gmail.com
one about signature - some people consider names useless if they don't
rearrange/skip defaults, some are happy with just checking alone.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e6770d93-d3d7-464c-8414-2c5dfd07789d%40isocpp.org.
Nicol Bolas
2018-08-22 20:47:29 UTC
Permalink
Post by m***@gmail.com
Post by Nicol Bolas
Post by m***@gmail.com
Post by Nicol Bolas
Post by m***@gmail.com
Are sure about that? Argument rearrangement is doable without changing
the signature (a.k.a. strong)
Maybe we have very different ideas about what "strong named parameters"
means. The question of "changing the signature" is not the distinction
between "strong" and "weak". At least, it's not the distinction that I'm
talking about it.
"Weak named parameters" to me refers to named parameters which are all
1. Optional. You can call a function that has named parameters without
naming the parameter(s) at the call site.
2. Ordered. The order of the arguments must match the parameter order
of the function, regardless of the names you specify at the call site.
3. Overload-neutral. The presence or absence of names at the call site
has no effect on function overloading.
Essentially, if your rules require that all named parameter function
calls will invoke the same function with the same behavior if you stripped
out all of the names, then the named parameter proposal is "weak".
Any named parameter feature which imposes rules antithetical to at
least one of the above is "strong". With the strongest being the antithesis
to all of them.
I see, for you weak refers to the notion the call is the same, but
unchecked, without them.
For me strong is referring to "does it introduce a new signature", the
same way strong typedef introduces a new type. Everything else is weak as
it is about the compiler not the code.
That's not what you said earlier
<https://groups.google.com/a/isocpp.org/d/msg/std-proposals/MbDT0vsA2j0/1VPQM7AsAAAJ>
Also, this obviously does not address the named arguments, *that are
Post by m***@gmail.com
optional, the "weak" ones*, so this solution will not make everyone
happy.
Emphasis added. And there's this post
<https://groups.google.com/a/isocpp.org/d/msg/std-proposals/MbDT0vsA2j0/uWG77JxeDQAJ>
//weak argument names, not mandatory
...
//strong argument name, adds an overload, not ignorable
Yes, that post is talking about how you would declare weak names
differently from strong names, but it's also talking about how they get
used at the call site: "not mandatory" vs. "not ignorable".
There is no contradiction, they are optional, and ignorable by the user
(he might not use them).
Now, it depends on how much features they have, they might also be as weak
as you assume they are, so they are (can be) ignored by the compiler as
well and the call is the same.
Most of the time here we talked about these weakest ones, and considered
"extra features" as "bonuses".
For me personally strong were always the one changing the signature,
that's why the first post about tags-as-labels was called "Strong named
arguments as tag overloads"
And weak for me were not rearranging or skipping, but having
defaulted-by-naming f(a:, b:, 10)
Of course even these are not ignorable as the call will fail without them.
Probably using the word ignorable was not correct.
In any case weak names are optional.
This is not to say, they do not affect overloading, they do, but only on
the call site.
void func(int a, int b);
void func(int a, int b: b=1, int c: c=2);
func(1, 3); //< overload 1
func(1, b: 3); //< overload 2
func(1, c: 3); //< overload 2
If names are important enough to affect what overload gets called, then
they ought to be part of a function's type. If they are truly "optional",
then they should not be able to affect overloading.

To me, "optional" means exactly that: optional. The choice of whether to
use names or not is entirely the prerogative of the caller. A caller should
be able to call the same function, providing the same parameters, without
using parameter names if they so desire.

You call the second overload, passing it the first two parameters. That is
not possible without using parameter names. You call the third overload,
passing only the first and third parameters. That too is not possible
without using parameter names.

For your proposal, parameter names are not optional. That's different from
saying that they are mandatory. There are cases in your design where you
can call a named parameter function overload without providing names for
those parameters.

The key here is that in your proposal, parameter names are *part of the
overload set's interface*. Just like the various conversion operators and
constructors on the types used as parameters.

That's what makes them different from default parameters: the fact that
`func(1, 3)` is not ambiguous. With default parameters, users who don't
specify all of the parameters can create ambiguous call relative to other
overloads in the set. With your design, that doesn't happen. This is what
makes the parameter name *more* than just a default argument; it makes it
part of the overload set's interface.

Changing the signature is a clear boundary in both semantics and
Post by m***@gmail.com
Post by Nicol Bolas
Post by m***@gmail.com
implementation.
But in the realm of non-changing-the-signature names, a lot can be done,
Post by m***@gmail.com
granted the calls *will* differ w/ and w/o names.
I think you're too focused on signature as the notion of a function's
identity. There are aspects of functions which are not their signature yet
directly relate to its identity.
Return values. If you declare two functions with the same name and
signatures with different return values, then you get a compile error.
`noexcept` works that way too; you can't be inconsistent about that. Both
of these are part of the function's type, but not its signature (though
`noexcept` can be cast away).
Contracts affect neither type nor signature, but even that requires some
basic consistency. You can declare contracts on a function or not. But all
contract declarations for the same function must be consistent.
If a parameter name can be used as a syntactic modifier when calling the
function (for the purposes of this discussion, anything which affects
actual code generation. This includes reordering of arguments), then that
name ought to be, if not part of the function's type, then at least have as
much consistency as its contracts. That is, if you want to be able to
reorder parameters, then the function should consistently assign each
parameter a single name or a single "unnamed".
In the original post about weak arguments, I suggested they obey the rules
of default arguments - you name your arguments only in the first
declaration. No names afterwards, not even the same.
auto child(name mother: mom, name dad);
// auto child(name mother: mom, name dad); *//< error*
// auto child(name mom, name father: dad); *//< error*
auto child(name mutter, vater); *//< OK*
auto child(name mother, name father) *//< OK*
{
// implementation
}
This seems the be the most consistent approach as (weak) named arguments
ultimately inhabit *exactly* the same design space as default arguments -
a compiler helper.
Default arguments generate code (conditionally or not). Weak named
arguments do not. I have some difficulty considering those to be "exactly
the same design space". Or even similar design spaces.

With default arguments the compiler is only obligated to copy-paste the
Post by m***@gmail.com
default expression if we don't pass a value.
- to only name-check
- to paste in place of name-only
- to paste on omission
- to rearrange
Post by Nicol Bolas
If names can be inconsistent and still affect syntax, bad things result.
Should it be done is a different matter, this is a debate as heated as
Post by m***@gmail.com
the one about signature - some people consider names useless if they don't
rearrange/skip defaults, some are happy with just checking alone.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/d1ae009f-97fa-47f6-aafb-b30bfe6e8d24%40isocpp.org.
Nicol Bolas
2018-08-22 20:57:05 UTC
Permalink
Post by Nicol Bolas
Default arguments generate code (conditionally or not). Weak named
arguments do not. I have some difficulty considering those to be "exactly
the same design space". Or even similar design spaces.
Disregard this paragraph; I meant to delete that before pressing "send".
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/a1a68d5a-8f60-4ec9-b49b-2b266d906d75%40isocpp.org.
m***@gmail.com
2018-08-23 08:34:42 UTC
Permalink
Post by m***@gmail.com
Post by m***@gmail.com
Post by Nicol Bolas
Post by m***@gmail.com
Post by Nicol Bolas
Post by m***@gmail.com
Are sure about that? Argument rearrangement is doable without
changing the signature (a.k.a. strong)
Maybe we have very different ideas about what "strong named
parameters" means. The question of "changing the signature" is not the
distinction between "strong" and "weak". At least, it's not the distinction
that I'm talking about it.
"Weak named parameters" to me refers to named parameters which are all
1. Optional. You can call a function that has named parameters without
naming the parameter(s) at the call site.
2. Ordered. The order of the arguments must match the parameter order
of the function, regardless of the names you specify at the call site.
3. Overload-neutral. The presence or absence of names at the call site
has no effect on function overloading.
Essentially, if your rules require that all named parameter function
calls will invoke the same function with the same behavior if you stripped
out all of the names, then the named parameter proposal is "weak".
Any named parameter feature which imposes rules antithetical to at
least one of the above is "strong". With the strongest being the antithesis
to all of them.
I see, for you weak refers to the notion the call is the same, but
unchecked, without them.
For me strong is referring to "does it introduce a new signature", the
same way strong typedef introduces a new type. Everything else is weak as
it is about the compiler not the code.
That's not what you said earlier
<https://groups.google.com/a/isocpp.org/d/msg/std-proposals/MbDT0vsA2j0/1VPQM7AsAAAJ>
Also, this obviously does not address the named arguments, *that are
Post by m***@gmail.com
optional, the "weak" ones*, so this solution will not make everyone
happy.
Emphasis added. And there's this post
<https://groups.google.com/a/isocpp.org/d/msg/std-proposals/MbDT0vsA2j0/uWG77JxeDQAJ>
//weak argument names, not mandatory
...
//strong argument name, adds an overload, not ignorable
Yes, that post is talking about how you would declare weak names
differently from strong names, but it's also talking about how they get
used at the call site: "not mandatory" vs. "not ignorable".
There is no contradiction, they are optional, and ignorable by the user
(he might not use them).
Now, it depends on how much features they have, they might also be as
weak as you assume they are, so they are (can be) ignored by the compiler
as well and the call is the same.
Most of the time here we talked about these weakest ones, and considered
"extra features" as "bonuses".
For me personally strong were always the one changing the signature,
that's why the first post about tags-as-labels was called "Strong named
arguments as tag overloads"
And weak for me were not rearranging or skipping, but having
defaulted-by-naming f(a:, b:, 10)
Of course even these are not ignorable as the call will fail without
them. Probably using the word ignorable was not correct.
In any case weak names are optional.
This is not to say, they do not affect overloading, they do, but only on
the call site.
void func(int a, int b);
Post by m***@gmail.com
void func(int a, int b: b=1, int c: c=2);
func(1, 3); //< overload 1
func(1, b: 3); //< overload 2
func(1, c: 3); //< overload 2
If names are important enough to affect what overload gets called, then
they ought to be part of a function's type. If they are truly "optional",
then they should not be able to affect overloading.
To me, "optional" means exactly that: optional. The choice of whether to
use names or not is entirely the prerogative of the caller. A caller should
be able to call the same function, providing the same parameters, without
using parameter names if they so desire.
You call the second overload, passing it the first two parameters. That is
not possible without using parameter names. You call the third overload,
passing only the first and third parameters. That too is not possible
without using parameter names.
For your proposal, parameter names are not optional. That's different from
saying that they are mandatory. There are cases in your design where you
can call a named parameter function overload without providing names for
those parameters.
The key here is that in your proposal, parameter names are *part of the
overload set's interface*. Just like the various conversion operators and
constructors on the types used as parameters.
That's what makes them different from default parameters: the fact that
`func(1, 3)` is not ambiguous. With default parameters, users who don't
specify all of the parameters can create ambiguous call relative to other
overloads in the set. With your design, that doesn't happen. This is what
makes the parameter name *more* than just a default argument; it makes it
part of the overload set's interface.
Boy, I made a mistake, func(1, 3) is *of course *ambiguous!

Bad example, here is the correct one

void func(int a, string b);
void func(int a, int b: b=1, string c: c="hi");
void func(int a, int b: b=1, int c: c=2);

func(1, "bye"); //< overload 1
func(1, c: "bye"); //< overload 2
func(1, c: 3); //< overload 3

The point was, on the call site (optional) names *can* affect overloading.

The more general argument was, optional names can service mega-functions,
as long as they allow skipping defaulted arguments.

But even mega-functions aside, *none of the current alternatives to the
above code are better*, even if possible - that's is way people want that
feature!
Post by m***@gmail.com
Changing the signature is a clear boundary in both semantics and
Post by m***@gmail.com
Post by Nicol Bolas
Post by m***@gmail.com
implementation.
But in the realm of non-changing-the-signature names, a lot can be done,
Post by m***@gmail.com
granted the calls *will* differ w/ and w/o names.
I think you're too focused on signature as the notion of a function's
identity. There are aspects of functions which are not their signature yet
directly relate to its identity.
Return values. If you declare two functions with the same name and
signatures with different return values, then you get a compile error.
`noexcept` works that way too; you can't be inconsistent about that. Both
of these are part of the function's type, but not its signature (though
`noexcept` can be cast away).
Contracts affect neither type nor signature, but even that requires some
basic consistency. You can declare contracts on a function or not. But all
contract declarations for the same function must be consistent.
If a parameter name can be used as a syntactic modifier when calling the
function (for the purposes of this discussion, anything which affects
actual code generation. This includes reordering of arguments), then that
name ought to be, if not part of the function's type, then at least have as
much consistency as its contracts. That is, if you want to be able to
reorder parameters, then the function should consistently assign each
parameter a single name or a single "unnamed".
In the original post about weak arguments, I suggested they obey the
rules of default arguments - you name your arguments only in the first
declaration. No names afterwards, not even the same.
auto child(name mother: mom, name dad);
// auto child(name mother: mom, name dad); *//< error*
// auto child(name mom, name father: dad); *//< error*
auto child(name mutter, vater); *//< OK*
auto child(name mother, name father) *//< OK*
{
// implementation
}
This seems the be the most consistent approach as (weak) named arguments
ultimately inhabit *exactly* the same design space as default arguments
- a compiler helper.
Default arguments generate code (conditionally or not). Weak named
arguments do not. I have some difficulty considering those to be "exactly
the same design space". Or even similar design spaces.
With default arguments the compiler is only obligated to copy-paste the
Post by m***@gmail.com
default expression if we don't pass a value.
- to only name-check
- to paste in place of name-only
- to paste on omission
- to rearrange
Post by Nicol Bolas
If names can be inconsistent and still affect syntax, bad things result.
Should it be done is a different matter, this is a debate as heated as
Post by m***@gmail.com
the one about signature - some people consider names useless if they don't
rearrange/skip defaults, some are happy with just checking alone.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/d04d85fa-a8c5-46e7-907e-acdf0754b0c3%40isocpp.org.
m***@gmail.com
2018-08-23 08:37:20 UTC
Permalink
Post by Nicol Bolas
Post by m***@gmail.com
Post by Nicol Bolas
Post by m***@gmail.com
Post by Nicol Bolas
Post by m***@gmail.com
Are sure about that? Argument rearrangement is doable without
changing the signature (a.k.a. strong)
Maybe we have very different ideas about what "strong named
parameters" means. The question of "changing the signature" is not the
distinction between "strong" and "weak". At least, it's not the distinction
that I'm talking about it.
"Weak named parameters" to me refers to named parameters which are all
1. Optional. You can call a function that has named parameters without
naming the parameter(s) at the call site.
2. Ordered. The order of the arguments must match the parameter order
of the function, regardless of the names you specify at the call site.
3. Overload-neutral. The presence or absence of names at the call site
has no effect on function overloading.
Essentially, if your rules require that all named parameter function
calls will invoke the same function with the same behavior if you stripped
out all of the names, then the named parameter proposal is "weak".
Any named parameter feature which imposes rules antithetical to at
least one of the above is "strong". With the strongest being the antithesis
to all of them.
I see, for you weak refers to the notion the call is the same, but
unchecked, without them.
For me strong is referring to "does it introduce a new signature", the
same way strong typedef introduces a new type. Everything else is weak as
it is about the compiler not the code.
That's not what you said earlier
<https://groups.google.com/a/isocpp.org/d/msg/std-proposals/MbDT0vsA2j0/1VPQM7AsAAAJ>
Also, this obviously does not address the named arguments, *that are
Post by m***@gmail.com
optional, the "weak" ones*, so this solution will not make everyone
happy.
Emphasis added. And there's this post
<https://groups.google.com/a/isocpp.org/d/msg/std-proposals/MbDT0vsA2j0/uWG77JxeDQAJ>
//weak argument names, not mandatory
...
//strong argument name, adds an overload, not ignorable
Yes, that post is talking about how you would declare weak names
differently from strong names, but it's also talking about how they get
used at the call site: "not mandatory" vs. "not ignorable".
There is no contradiction, they are optional, and ignorable by the user
(he might not use them).
Now, it depends on how much features they have, they might also be as
weak as you assume they are, so they are (can be) ignored by the compiler
as well and the call is the same.
Most of the time here we talked about these weakest ones, and considered
"extra features" as "bonuses".
For me personally strong were always the one changing the signature,
that's why the first post about tags-as-labels was called "Strong named
arguments as tag overloads"
And weak for me were not rearranging or skipping, but having
defaulted-by-naming f(a:, b:, 10)
Of course even these are not ignorable as the call will fail without
them. Probably using the word ignorable was not correct.
In any case weak names are optional.
This is not to say, they do not affect overloading, they do, but only on
the call site.
void func(int a, int b);
void func(int a, int b: b=1, int c: c=2);
func(1, 3); //< overload 1
func(1, b: 3); //< overload 2
func(1, c: 3); //< overload 2
If names are important enough to affect what overload gets called, then
they ought to be part of a function's type. If they are truly "optional",
then they should not be able to affect overloading.
To me, "optional" means exactly that: optional. The choice of whether to
use names or not is entirely the prerogative of the caller. A caller should
be able to call the same function, providing the same parameters, without
using parameter names if they so desire.
You call the second overload, passing it the first two parameters. That is
not possible without using parameter names. You call the third overload,
passing only the first and third parameters. That too is not possible
without using parameter names.
For your proposal, parameter names are not optional. That's different from
saying that they are mandatory. There are cases in your design where you
can call a named parameter function overload without providing names for
those parameters.
The key here is that in your proposal, parameter names are *part of the
overload set's interface*. Just like the various conversion operators and
constructors on the types used as parameters.
That's what makes them different from default parameters: the fact that
`func(1, 3)` is not ambiguous. With default parameters, users who don't
specify all of the parameters can create ambiguous call relative to other
overloads in the set. With your design, that doesn't happen. This is what
makes the parameter name *more* than just a default argument; it makes it
part of the overload set's interface.
Boy, I made a mistake, func(1, 3) is of course ambiguous!

Bad example, here is the correct one:

void func(int a, string b);
void func(int a, int b: b=1, string c: c="hi");
void func(int a, int b: b=1, int c: c=2);

func(1, "bye"); //< overload 1
func(1, c: "bye"); //< overload 2
func(1, c: 3); //< overload 3

The point was, on the call site (optional) names *can* affect overloading.

The more general argument was, optional names can service mega-functions,
as long as they allow skipping defaulted arguments.
But even mega-functions aside, *none of the current alternatives to the
above code are better*, even if possible - that's is way people want that
feature!
Post by Nicol Bolas
Changing the signature is a clear boundary in both semantics and
Post by m***@gmail.com
Post by Nicol Bolas
Post by m***@gmail.com
implementation.
But in the realm of non-changing-the-signature names, a lot can be done,
Post by m***@gmail.com
granted the calls *will* differ w/ and w/o names.
I think you're too focused on signature as the notion of a function's
identity. There are aspects of functions which are not their signature yet
directly relate to its identity.
Return values. If you declare two functions with the same name and
signatures with different return values, then you get a compile error.
`noexcept` works that way too; you can't be inconsistent about that. Both
of these are part of the function's type, but not its signature (though
`noexcept` can be cast away).
Contracts affect neither type nor signature, but even that requires some
basic consistency. You can declare contracts on a function or not. But all
contract declarations for the same function must be consistent.
If a parameter name can be used as a syntactic modifier when calling the
function (for the purposes of this discussion, anything which affects
actual code generation. This includes reordering of arguments), then that
name ought to be, if not part of the function's type, then at least have as
much consistency as its contracts. That is, if you want to be able to
reorder parameters, then the function should consistently assign each
parameter a single name or a single "unnamed".
In the original post about weak arguments, I suggested they obey the
rules of default arguments - you name your arguments only in the first
declaration. No names afterwards, not even the same.
auto child(name mother: mom, name dad);
// auto child(name mother: mom, name dad); *//< error*
// auto child(name mom, name father: dad); *//< error*
auto child(name mutter, vater); *//< OK*
auto child(name mother, name father) *//< OK*
{
// implementation
}
This seems the be the most consistent approach as (weak) named arguments
ultimately inhabit *exactly* the same design space as default arguments
- a compiler helper.
Default arguments generate code (conditionally or not). Weak named
arguments do not. I have some difficulty considering those to be "exactly
the same design space". Or even similar design spaces.
With default arguments the compiler is only obligated to copy-paste the
Post by m***@gmail.com
default expression if we don't pass a value.
- to only name-check
- to paste in place of name-only
- to paste on omission
- to rearrange
Post by Nicol Bolas
If names can be inconsistent and still affect syntax, bad things result.
Should it be done is a different matter, this is a debate as heated as
Post by m***@gmail.com
the one about signature - some people consider names useless if they don't
rearrange/skip defaults, some are happy with just checking alone.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/cf7ed305-cca4-44d3-a50c-1596c85340ff%40isocpp.org.
Vicente J. Botet Escriba
2018-08-20 22:27:02 UTC
Permalink
Post by Nicol Bolas
On Monday, August 20, 2018 at 2:15:17 AM UTC-4, Vicente J.
On Sunday, August 19, 2018 at 5:21:11 PM UTC-4, Vicente
On Sunday, August 19, 2018 at 7:46:58 PM UTC+3,
On Sunday, August 19, 2018 at 3:26:12 PM UTC+3,
Independently of the language feature,
using a tag type allows to
transport the tag between different
functions. In addition, you cannot
change the class constructor name, so you
will need a tag to be able to
overload it. Take for example the
in_place_t tag.
I have thoroughly explored that idea a month
https://groups.google.com/a/isocpp.org/d/msg/std-proposals/tPtdQE2GXb0/4OjT5Z4pBQAJ
<https://groups.google.com/a/isocpp.org/d/msg/std-proposals/tPtdQE2GXb0/4OjT5Z4pBQAJ>
Feel free to comment there, I am undecided on
the topic.
I'm not sure yet we need some syntactic sugar
for this tag dispatching feature neither.
I'm just trying to separate the named parameter
part from the overload part as orthogonal features.
You go too far for my taste in your proposal and
you propose to have all at once. I'll be against
such a feature.
Can you elaborate a bit more, what are your
expectations and where should a line be drawn? As
you can see in the comments to the post, there are
similar concerns.
In any case it is not a proposal, but an
investigation. It is clear tags have overlap with
strong names, and if we can get an attractive
proposition, based on tags, we can mark at least one
part (the harder part?) of the named arguments
equation "fixed".
I would like to see the two features proposed
independently.
I see more added value for weak named parameters that
are optional and opt in on the author side (as the
workarounds are not always friendly) than the strong
named parameters that can be used to overload
function or constructors and that are not optional
(as tag types are an almost friendly library
solution, as the standard library has showed already
multiple times).
The problem with having them be independent is that
they're /not/ independent. They're both playing around in
the same space: invoking a parameter's name when you call
the function.
The first question any named parameter proposal has to
answer is whether to rely on the existing parameter name
infrastructure or to use a special way to define them.
There are arguments for both weak and strong parameters
to want to have syntax to declare named parameters on a
function. This is because, by having users rely on them
to some degree (even if mis-matched naming is just a
warning), you are making those parameter names part of
the interface of the API. And that's different from how
parameter names have been treated in the past.
I'm not for strong named parameters. For me, this is a
disguised form of mixing weak named parameters and tag
dispatching. This is why I believe the features are
independent.
Now you can put them together and obtain named parameters
and tag dispatch.
If you try to develop weak and strong parameters
completely independently, then what you can end up with
are two proposals that provide completely different ways
of declaring such parameters. And considering all of the
stuff that we keep cramming into function declarations
these days, giving parameters /three names/ is utterly
absurd. Even if you forbid weak parameter names on
functions with strong names, that's still 3 separate
syntaxes for declaring parameter names.
If we want weak and strong named parameters and don't see
another solution than having two syntaxes :(
If that's the case, then we shouldn't have weak named
parameters at all. Remember: weak named parameters are purely
notational; they catch errors. That makes them a "nice to
have". Strong named parameters provide genuine functionality,
allowing you to express things that could not be expressed before.
If the design space is sufficiently constrained to only permit
one or the other, then it should be the one that actually does
something.
I don't believe that we want non op in named parametrs, so
each one of the weak/strong alternatives would need a
specific syntax.
So I don't think it's reasonable to develop the two
proposals completely independently from one another. They
should at least be developed with the knowledge that the
other is a possibility, and with syntax that can
reasonably fit together.
Maybe you are right, but I would like that the proposal
are clearly separated, so that we can be agains one from
or the other.
So, you can't be against one part of a proposal? The standards
committee does it all the time.
Lastly, it should be noted that tagged dispatch doesn't
functions that take stupidly large numbers of relatively
independent parameters, but for some reason don't want to
take them as a convenient aggregate. This is a use case
that some people want to support, to avoid conceptual
two-stage construction.
IMHO, this case is covered by weak named parameters already.
Then perhaps you're not understanding what a "mega-function"
is. We're talking about functions with /dozens/ of parameters,
most of which are optional. Consider all of the various
parameters you deal with when setting up a window. Window
styles, size, position, hierarchy, font choice, and other
things. Each of those are conceptually one or more parameters
to the window creation function.
"Ideally", these would be literal parameters to a hypothetical
Window class's constructor. But they're not; most such classes
give relatively limited numbers of parameters to the Window's
constructor. The rest are values set after the Window's
construction, which means that defaults are used until those
get set. Basically, it's two-stage construction.
The only way you can get the "ideal" case is if order for
parameters is /completely removed/ for such functions. You can
specify the arguments in any order when you call them, and the
caller can default any parameter with a default value simply
by not specifying it.
Weak named parameters can't do that. Tag dispatch can't do
that (not without extraordinary pain on the callee side). Even
designated initializers have to be specified in the right order.
Are sure about that? Argument rearrangement is doable without
changing the signature (a.k.a. strong)
Maybe we have very different ideas about what "strong named
parameters" means. The question of "changing the signature" is not the
distinction between "strong" and "weak". At least, it's not the
distinction that I'm talking about it.
Maybe it is not for you. It is for me and others. Another distinction
that we have not discused so much, is if the names are needed for the
arguments or are optional.
Post by Nicol Bolas
"Weak named parameters" to me refers to named parameters which are all
1. Optional. You can call a function that has named parameters without
naming the parameter(s) at the call site.
2. Ordered. The order of the arguments must match the parameter order
of the function, regardless of the names you specify at the call site.
Why? This is a simplification, that could be wished or not.
Post by Nicol Bolas
3. Overload-neutral. The presence or absence of names at the call site
has no effect on function overloading.
So it doesn't change the function signature.

4. You are missing that we can skip some of them.
Post by Nicol Bolas
Essentially, if your rules require that all named parameter function
calls will invoke the same function with the same behavior if you
stripped out all of the names, then the named parameter proposal is
"weak".
Any named parameter feature which imposes rules antithetical to at
least one of the above is "strong". With the strongest being the
antithesis to all of them.
You should write a proposal so that we know what you are talking of :)


Vicente
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/409803d8-c7cc-79ac-2e1c-d823b6cc0b36%40wanadoo.fr.
Vicente J. Botet Escriba
2018-08-20 22:21:47 UTC
Permalink
Post by Nicol Bolas
On Monday, August 20, 2018 at 2:15:17 AM UTC-4, Vicente J. Botet
On Sunday, August 19, 2018 at 5:21:11 PM UTC-4, Vicente J. Botet
On Sunday, August 19, 2018 at 7:46:58 PM UTC+3, Vicente J.
On Sunday, August 19, 2018 at 3:26:12 PM UTC+3, Vicente
Independently of the language feature, using a tag
type allows to
transport the tag between different functions. In
addition, you cannot
change the class constructor name, so you will need
a tag to be able to
overload it. Take for example the in_place_t tag.
https://groups.google.com/a/isocpp.org/d/msg/std-proposals/tPtdQE2GXb0/4OjT5Z4pBQAJ
<https://groups.google.com/a/isocpp.org/d/msg/std-proposals/tPtdQE2GXb0/4OjT5Z4pBQAJ>
Feel free to comment there, I am undecided on the topic.
I'm not sure yet we need some syntactic sugar for this
tag dispatching feature neither.
I'm just trying to separate the named parameter part
from the overload part as orthogonal features.
You go too far for my taste in your proposal and you
propose to have all at once. I'll be against such a feature.
Can you elaborate a bit more, what are your expectations and
where should a line be drawn? As you can see in the comments
to the post, there are similar concerns.
In any case it is not a proposal, but an investigation. It
is clear tags have overlap with strong names, and if we can
get an attractive proposition, based on tags, we can mark at
least one part (the harder part?) of the named arguments
equation "fixed".
I would like to see the two features proposed independently.
I see more added value for weak named parameters that are
optional and opt in on the author side (as the workarounds
are not always friendly) than the strong named parameters
that can be used to overload function or constructors and
that are not optional (as tag types are an almost friendly
library solution, as the standard library has showed already
multiple times).
The problem with having them be independent is that they're /not/
invoking a parameter's name when you call the function.
The first question any named parameter proposal has to answer is
whether to rely on the existing parameter name infrastructure or
to use a special way to define them. There are arguments for both
weak and strong parameters to want to have syntax to declare
named parameters on a function. This is because, by having users
rely on them to some degree (even if mis-matched naming is just a
warning), you are making those parameter names part of the
interface of the API. And that's different from how parameter
names have been treated in the past.
I'm not for strong named parameters. For me, this is a disguised
form of mixing weak named parameters and tag dispatching. This is
why I believe the features are independent.
Now you can put them together and obtain named parameters and tag dispatch.
If you try to develop weak and strong parameters completely
independently, then what you can end up with are two proposals
that provide completely different ways of declaring such
parameters. And considering all of the stuff that we keep
cramming into function declarations these days, giving parameters
/three names/ is utterly absurd. Even if you forbid weak
parameter names on functions with strong names, that's still 3
separate syntaxes for declaring parameter names.
If we want weak and strong named parameters and don't see another
solution than having two syntaxes :(
If that's the case, then we shouldn't have weak named parameters at
all. Remember: weak named parameters are purely notational; they catch
errors. That makes them a "nice to have". Strong named parameters
provide genuine functionality, allowing you to express things that
could not be expressed before.
If the design space is sufficiently constrained to only permit one or
the other, then it should be the one that actually does something.
Well, I believe that if the design space is limited, I prefer to have
named parameters that don't change the signature.

The other I can do them with tag types :)

You see, we disagree.
Post by Nicol Bolas
I don't believe that we want non op in named parametrs, so each
one of the weak/strong alternatives would need a specific syntax.
So I don't think it's reasonable to develop the two proposals
completely independently from one another. They should at least
be developed with the knowledge that the other is a possibility,
and with syntax that can reasonably fit together.
Maybe you are right, but I would like that the proposal are
clearly separated, so that we can be agains one from or the other.
So, you can't be against one part of a proposal? The standards
committee does it all the time.
Better to split them. For me of course.
Post by Nicol Bolas
Lastly, it should be noted that tagged dispatch doesn't help with
what I will refer to as "mega-functions": functions that take
stupidly large numbers of relatively independent parameters, but
for some reason don't want to take them as a convenient
aggregate. This is a use case that some people want to support,
to avoid conceptual two-stage construction.
IMHO, this case is covered by weak named parameters already.
Then perhaps you're not understanding what a "mega-function" is. We're
talking about functions with /dozens/ of parameters, most of which are
optional. Consider all of the various parameters you deal with when
setting up a window. Window styles, size, position, hierarchy, font
choice, and other things. Each of those are conceptually one or more
parameters to the window creation function.
Maybe you don't understand the same thing as me. week named parameters
allow optionals for me :)
Post by Nicol Bolas
"Ideally", these would be literal parameters to a hypothetical Window
class's constructor. But they're not; most such classes give
relatively limited numbers of parameters to the Window's constructor.
The rest are values set after the Window's construction, which means
that defaults are used until those get set. Basically, it's two-stage
construction.
The only way you can get the "ideal" case is if order for parameters
is /completely removed/ for such functions. You can specify the
arguments in any order when you call them, and the caller can default
any parameter with a default value simply by not specifying it.
Weak named parameters can't do that. Tag dispatch can't do that (not
without extraordinary pain on the callee side). Even designated
initializers have to be specified in the right order.
Why are you so sure my weak named parameters can't do that?

Vicente
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/694eec5e-0bb9-6a94-21db-d0112db55a73%40wanadoo.fr.
Matthew Woehlke
2018-08-23 19:00:19 UTC
Permalink
Post by Nicol Bolas
The only way you can get the "ideal" case is if order for parameters is *completely
removed* for such functions. You can specify the arguments in any order
when you call them, and the caller can default any parameter with a default
value simply by not specifying it.
Um... why? Why is it a problem to enforce that, if you specify a font,
that has to be specified before a palette?

You need to be able to *skip* parameters. I don't see why you need to be
able to *reorder* parameters...
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/a47df58c-0dde-3a96-4d4a-70aa2bd403e0%40gmail.com.
Vicente J. Botet Escriba
2018-08-20 06:18:42 UTC
Permalink
On Sunday, August 19, 2018 at 5:21:11 PM UTC-4, Vicente J. Botet
On Sunday, August 19, 2018 at 7:46:58 PM UTC+3, Vicente J. Botet
On Sunday, August 19, 2018 at 3:26:12 PM UTC+3, Vicente J.
Independently of the language feature, using a tag type
allows to
transport the tag between different functions. In
addition, you cannot
change the class constructor name, so you will need a
tag to be able to
overload it. Take for example the in_place_t tag.
https://groups.google.com/a/isocpp.org/d/msg/std-proposals/tPtdQE2GXb0/4OjT5Z4pBQAJ
<https://groups.google.com/a/isocpp.org/d/msg/std-proposals/tPtdQE2GXb0/4OjT5Z4pBQAJ>
Feel free to comment there, I am undecided on the topic.
I'm not sure yet we need some syntactic sugar for this tag
dispatching feature neither.
I'm just trying to separate the named parameter part from the
overload part as orthogonal features.
You go too far for my taste in your proposal and you propose
to have all at once. I'll be against such a feature.
Can you elaborate a bit more, what are your expectations and
where should a line be drawn? As you can see in the comments to
the post, there are similar concerns.
In any case it is not a proposal, but an investigation. It is
clear tags have overlap with strong names, and if we can get an
attractive proposition, based on tags, we can mark at least one
part (the harder part?) of the named arguments equation "fixed".
I would like to see the two features proposed independently.
I see more added value for weak named parameters that are optional
and opt in on the author side (as the workarounds are not always
friendly) than the strong named parameters that can be used to
overload function or constructors and that are not optional (as
tag types are an almost friendly library solution, as the standard
library has showed already multiple times).
The problem with having them be independent is that they're /not/
independent. They're both playing around in the same space: invoking a
parameter's name when you call the function.
The first question any named parameter proposal has to answer is
whether to rely on the existing parameter name infrastructure or to
use a special way to define them. There are arguments for both weak
and strong parameters to want to have syntax to declare named
parameters on a function. This is because, by having users rely on
them to some degree (even if mis-matched naming is just a warning),
you are making those parameter names part of the interface of the API.
And that's different from how parameter names have been treated in the
past.
I'm not for strong named parameters. For me, this is a disguised form of
mixing weak named parameters and tag dispatching. This is why I believe
the features are independent.
Now you can put them together and obtain named parameters and tag dispatch.
If you try to develop weak and strong parameters completely
independently, then what you can end up with are two proposals that
provide completely different ways of declaring such parameters. And
considering all of the stuff that we keep cramming into function
declarations these days, giving parameters /three names/ is utterly
absurd. Even if you forbid weak parameter names on functions with
strong names, that's still 3 separate syntaxes for declaring parameter
names.
If we want weak and strong named parameters and don't see another
solution than having two syntax :(

I don't believe that we want non op in named parameters, so each one of
the weak/strong alternatives would need a specific syntax.
So I don't think it's reasonable to develop the two proposals
completely independently from one another. They should at least be
developed with the knowledge that the other is a possibility, and with
syntax that can reasonably fit together.
Maybe you are right, but I would like that the proposal are clearly
separated, so that we can be against one from or the other.
Lastly, it should be noted that tagged dispatch doesn't help with what
I will refer to as "mega-functions": functions that take stupidly
large numbers of relatively independent parameters, but for some
reason don't want to take them as a convenient aggregate. This is a
use case that some people want to support, to avoid conceptual
two-stage construction.
IMHO, this case is covered by weak named parameters already.
If you accept that your signature changes and require that the argument
must be named, strong named parameters could as well cover it.

If you don't accept that your signature changes and require that the
argument must be named, weak named parameters + some static analysis
tool (as clang-tidy) help could as well cover it (but not that the
syantax will be already defined by the standard).

Maybe we need strong named parameters that don't change the signatures
as well ;-)




Vicente
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e97ada03-8b7c-39c3-cc85-514a3b67091d%40wanadoo.fr.
m***@gmail.com
2018-08-20 07:25:06 UTC
Permalink
On Monday, August 20, 2018 at 12:21:11 AM UTC+3, Vicente J. Botet Escriba
On Sunday, August 19, 2018 at 7:46:58 PM UTC+3, Vicente J. Botet Escriba
On Sunday, August 19, 2018 at 3:26:12 PM UTC+3, Vicente J. Botet Escriba
Independently of the language feature, using a tag type allows to
transport the tag between different functions. In addition, you cannot
change the class constructor name, so you will need a tag to be able to
overload it. Take for example the in_place_t tag.
https://groups.google.com/a/isocpp.org/d/msg/std-proposals/tPtdQE2GXb0/4OjT5Z4pBQAJ
Feel free to comment there, I am undecided on the topic.
I'm not sure yet we need some syntactic sugar for this tag dispatching
feature neither.
I'm just trying to separate the named parameter part from the overload
part as orthogonal features.
You go too far for my taste in your proposal and you propose to have all
at once. I'll be against such a feature.
Can you elaborate a bit more, what are your expectations and where should
a line be drawn? As you can see in the comments to the post, there are
similar concerns.
In any case it is not a proposal, but an investigation. It is clear tags
have overlap with strong names, and if we can get an attractive
proposition, based on tags, we can mark at least one part (the harder
part?) of the named arguments equation "fixed".
I would like to see the two features proposed independently.
I see more added value for weak named parameters that are optional and opt
in on the author side (as the workarounds are not always friendly) than the
strong named parameters that can be used to overload function or
constructors and that are not optional (as tag types are an almost friendly
library solution, as the standard library has showed already multiple
times).
This is also my PoV in general, especially with more friendly tags.
However, many people hate the idea names will be for weak only and they are
left to use workarounds for overload resolution - after all, they consider
names the correct way of handling this.

The second issue is, neither tags nor named functions are perfect
solutions. Tags are a technically a working solution, but they don't convey
the same meaning as label would.
Natural naming like for:, to:, with:, if:, relativeTo:, ignoring:,
including:, are pretty much unattainable for tags, both for the words that
can be used and the lack of semicolon to give context when reading the code.

If we say "just use tags", people will still demand strong names, this is
what I am trying to say.

Sadly, strong names do not eliminate the need for tags!
To still have tag as an idiom AND strong names, this is probably too much,
but I might be wrong -
after all if we eliminate static/free functions as constructors, it will be
a massive win, even if there are some use for tags left.
This is what I mean by "where should we draw the line".
Vicente
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/a1ea778c-4b2c-4af0-90ac-0ba0792cc439%40isocpp.org.
Matthew Woehlke
2018-08-23 17:18:54 UTC
Permalink
Lastly, it should be noted that tagged dispatch doesn't help with what I
will refer to as "mega-functions": functions that take stupidly large
numbers of relatively independent parameters, but for some reason don't
want to take them as a convenient aggregate. This is a use case that some
people want to support, to avoid conceptual two-stage construction.
A good exercise in "why do we want named parameters" (at least for this
use case) would be to try to implement the API of Python's argparse in
C++17.
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/62d799ef-6e17-2fe4-66f2-a09524cbce25%40gmail.com.
Justin Bassett
2018-08-17 15:17:33 UTC
Permalink
On Fri, Aug 17, 2018, 7:46 AM Vicente J. Botet Escriba <
* only one set of names is possible for all the TU (this need the kind of
mangling you are suggesting). I can live without this. IIRC this was the
approach that was rejected by the committee.
Is there a way I can see the comments the committee has made on a proposal?
My impression from my research was counter to this: I thought the committee
didn't like that names could vary across translation units. I would like to
read the comments on proposals, rather than just guess what the committee's
concerns are
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAPuuy5eVi7Wns3augMyk0-F3eqCdLBZZ7Qwjmgsp-Hfjc0sq-A%40mail.gmail.com.
Vicente J. Botet Escriba
2018-08-18 08:08:42 UTC
Permalink
Post by Justin Bassett
On Fri, Aug 17, 2018, 7:46 AM Vicente J. Botet Escriba
* only one set of names is possible for all the TU (this need the
kind of mangling you are suggesting). I can live without this.
IIRC this was the approach that was rejected by the committee.
Is there a way I can see the comments the committee has made on a
proposal? My impression from my research was counter to this: I
thought the committee didn't like that names could vary across
translation units. I would like to read the comments on proposals,
rather than just guess what the committee's concerns are
I don't know when this was reviewed. Maybe you can contact the author
directly.

Vicente
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/b9b3e05c-a9e3-e67b-35a0-549b60a556a8%40wanadoo.fr.
m***@gmail.com
2018-08-16 15:45:02 UTC
Permalink
Post by Matthew Woehlke
Post by David Brown
I am at a loss to why people key wanting to make this such a complicated
issue.
[...]
2. The primary use is to check that parameters are given in the right
order, with the ability to re-order parameters at the call site as a
secondary concern.
...probably because plenty of people disagree with this point. AFAIAC,
void foo(int, int :a = 1, int :b = 2, int :c = 12);
foo(3, b: 5); // foo(3, 1, 5, 12)
void bar(int :a);
void bar(int :x); // distinct overload
...is pointless. Checking argument order is, IMHO, not only *not* "the
primary use", but *optional*.
Names part of the signature makes them mandatory. There are plenty of ways
to do that today - types, tags, function names.
And all work with forwarding.

I might disagree on a lot of points with the OP, but the primary goal is to
confirm parameters are semantically correct when that meaning is hard,
incorrect or clumsy to express as a separate type.
Bonus is defaulted-params-in-the-middle which will enable foo(3, a:, b: 5);
and *eventually* a bonus rearrange.
Post by Matthew Woehlke
Post by David Brown
3. It should not require changes to existing code, new ABIs, new object
file formats, or anything more than minimal changes to the compiler
front-end.
While I agree we'd like to obtain this, I don't think it's realistic...
which probably has a lot to do with why no proposal has (yet) been accepted.
Post by David Brown
We do /not/ want this to be part of a function's signature - there is no
benefit to it,
Wrong: overloading.
Python doesn't have this problem because a) there is no such thing as
separate declarations and definitions in Python, and b) Python has no
overloading, period.
These aren't the case in C++, and trying to ignore the ramifications of
these points as they apply to named arguments is IMO a recipe for failure.
Also, forwarding needs to work somehow. I don't see how this can be done
without making names part of the type system.
Post by David Brown
(But the added complexity and implementation effort needed would not
be worth it - such costly ideas hinder the adoption of the main
feature. And there would be nothing to stop this being added in some
way at a later date.)
I disagree; if you make named arguments *not* part of the ABI, I think
it will be very hard to go back and change that decision.
Post by David Brown
foo(.b = 2, .a = 1, 3);
This is confusing, and IMO should be prohibited. Just like it is in Python.
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/13e5bd78-7ce7-4f00-a213-bd89f1d74c5d%40isocpp.org.
Justin Bassett
2018-08-17 04:04:34 UTC
Permalink
Post by Matthew Woehlke
Post by David Brown
I am at a loss to why people key wanting to make this such a complicated
issue.
[...]
2. The primary use is to check that parameters are given in the right
order, with the ability to re-order parameters at the call site as a
secondary concern.
...probably because plenty of people disagree with this point. AFAIAC,
void foo(int, int :a = 1, int :b = 2, int :c = 12);
foo(3, b: 5); // foo(3, 1, 5, 12)
void bar(int :a);
void bar(int :x); // distinct overload
...is pointless. Checking argument order is, IMHO, not only *not* "the
primary use", but *optional*.
I agree for the most part, but I disagree that this should be a valid
overload set, unless parameters are name-only:

void bar(int :a);
void bar(int :x);

The problem is that bar(4) is ambiguous. It would be better to catch this
at the declaration rather than at the first ambiguous point of use.
Overloading on name-only parameters is just fine.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAPuuy5cqjR6C%3D--pD1fZQxHPQwU94dMLhTWD9MvkU6twszVhGg%40mail.gmail.com.
Matthew Woehlke
2018-08-17 16:54:14 UTC
Permalink
Post by Justin Bassett
I agree for the most part, but I disagree that this should be a valid
void bar(int :a);
void bar(int :x);
The problem is that bar(4) is ambiguous.
So what?

void foo(int, double=1.);
void foo(int, int=2);

foo(1); // error: ambiguous

void bar(int :a); // #1
void bar(int :x); // #2

bar(1); // error: ambiguous
bar(.z=1); // error: no matching declaration
bar(.a=1); // okay, calls #1

I don't see a problem here.
Post by Justin Bassett
Overloading on name-only parameters is just fine.
What is a "name only" parameter?
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/8cf7a602-a287-8968-368b-132f2923539e%40gmail.com.
Nicol Bolas
2018-08-16 15:42:01 UTC
Permalink
Designated initializers effectively gives you most of these features. That
is, if you declare your function as taking a single aggregate of
parameters, you can get about 90% of what you want.

A function with named parameters would have that set of named parameters as
part of its ABI:

struct FoosParams {int x; int y;};
void foo(FoosParams params);

You would have the ability to call it with or without names, but you can't
mix-and-match:

foo({.x = 5, .y = 12});
foo({5, 12});
foo({.x = 5, 12}); //ill-formed

You can have default parameters without positional order:

struct FoosParams {int x = 5; int y;}
void foo(FoosParams params);
foo({.y = 12});

It even allows meaningful overloading on "names" alone:

struct complex_ri {double r, double i};
struct complex_rt {double r, double theta_rad};

//Constructors

complex(complex_ri ri);
complex(complex_rt rt);

//usage
complex a({.r = 5.0d, .i = 3.0d});
complex b({.r = 4.2d, .theta_rad = 2});
complex c({5.0d, 3.0d}); //ill-formed, due to call ambiguity.

I believe that works with designated initializes in C++20, but I admittedly
have not studied the proposal that closely. So it may not work.

This even works through forwarding, but it does require you to explicitly
name the `FoosParams` type at the call site:

std::function<void(FoosParams)> foofunctor = &foo;
foofunctor(FoosParams{.x = 5, .y = 12});

Now of course, this way of handling named parameters causes a bunch of
warts. Anytime you want to create such a function, you have to explicitly
create a type for it. Forwarding, or any usage of the signature, requires
using that typename. And while you can forward them, the forwarding
function only sees it as a single struct, not a set of values. This makes
doing things like transforming parameters impossible (well, without
reflection, and even then, your code would have to assume that the single
struct is a set of "parameters" to be transformed). And so forth.

But overall, it gets the job done without language changes. It's not clean,
so it won't be used universally or anything, but it works well enough that
it can be used in places where the ambiguity of a call is worse than having
to pass a struct.

The way I see it, the only reason to promote named parameters to a language
feature is to make usage of them more widespread. That is, rather than
restricting them to cases of significant ambiguity where the cost of a
struct is better than without it, you would be able to use them in cases
where you don't really have to.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/5d064165-5a58-4810-90f7-aa3732be92db%40isocpp.org.
m***@gmail.com
2018-08-16 16:02:09 UTC
Permalink
Post by Nicol Bolas
Designated initializers effectively gives you most of these features. That
is, if you declare your function as taking a single aggregate of
parameters, you can get about 90% of what you want.
A function with named parameters would have that set of named parameters
struct FoosParams {int x; int y;};
void foo(FoosParams params);
You would have the ability to call it with or without names, but you can't
foo({.x = 5, .y = 12});
foo({5, 12});
foo({.x = 5, 12}); //ill-formed
struct FoosParams {int x = 5; int y;}
void foo(FoosParams params);
foo({.y = 12});
struct complex_ri {double r, double i};
struct complex_rt {double r, double theta_rad};
//Constructors
complex(complex_ri ri);
complex(complex_rt rt);
//usage
complex a({.r = 5.0d, .i = 3.0d});
complex b({.r = 4.2d, .theta_rad = 2});
complex c({5.0d, 3.0d}); //ill-formed, due to call ambiguity.
I believe that works with designated initializes in C++20, but I
admittedly have not studied the proposal that closely. So it may not work.
This even works through forwarding, but it does require you to explicitly
std::function<void(FoosParams)> foofunctor = &foo;
foofunctor(FoosParams{.x = 5, .y = 12});
Now of course, this way of handling named parameters causes a bunch of
warts. Anytime you want to create such a function, you have to explicitly
create a type for it. Forwarding, or any usage of the signature, requires
using that typename. And while you can forward them, the forwarding
function only sees it as a single struct, not a set of values. This makes
doing things like transforming parameters impossible (well, without
reflection, and even then, your code would have to assume that the single
struct is a set of "parameters" to be transformed). And so forth.
Add to all this,
- no IntelliSense will ever help you ,
- the implementation is severely affected (structured bindings to the
rescue I guess...)
- overloading is surreal
Post by Nicol Bolas
But overall, it gets the job done without language changes. It's not
clean, so it won't be used universally or anything, but it works well
enough that it can be used in places where the ambiguity of a call is worse
than having to pass a struct.
The way I see it, the only reason to promote named parameters to a
language feature is to make usage of them more widespread. That is, rather
than restricting them to cases of significant ambiguity where the cost of a
struct is better than without it, you would be able to use them in cases
where you don't really have to.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/ee95fce0-13e7-4e6c-883f-752589489362%40isocpp.org.
Nicol Bolas
2018-08-16 16:28:59 UTC
Permalink
Post by m***@gmail.com
Post by Nicol Bolas
Designated initializers effectively gives you most of these features.
That is, if you declare your function as taking a single aggregate of
parameters, you can get about 90% of what you want.
A function with named parameters would have that set of named parameters
struct FoosParams {int x; int y;};
void foo(FoosParams params);
You would have the ability to call it with or without names, but you
foo({.x = 5, .y = 12});
foo({5, 12});
foo({.x = 5, 12}); //ill-formed
struct FoosParams {int x = 5; int y;}
void foo(FoosParams params);
foo({.y = 12});
struct complex_ri {double r, double i};
struct complex_rt {double r, double theta_rad};
//Constructors
complex(complex_ri ri);
complex(complex_rt rt);
//usage
complex a({.r = 5.0d, .i = 3.0d});
complex b({.r = 4.2d, .theta_rad = 2});
complex c({5.0d, 3.0d}); //ill-formed, due to call ambiguity.
I believe that works with designated initializes in C++20, but I
admittedly have not studied the proposal that closely. So it may not work.
This even works through forwarding, but it does require you to explicitly
std::function<void(FoosParams)> foofunctor = &foo;
foofunctor(FoosParams{.x = 5, .y = 12});
Now of course, this way of handling named parameters causes a bunch of
warts. Anytime you want to create such a function, you have to explicitly
create a type for it. Forwarding, or any usage of the signature, requires
using that typename. And while you can forward them, the forwarding
function only sees it as a single struct, not a set of values. This makes
doing things like transforming parameters impossible (well, without
reflection, and even then, your code would have to assume that the single
struct is a set of "parameters" to be transformed). And so forth.
Add to all this,
"And so forth" means that the list is not comprehensive. But that being
Post by m***@gmail.com
- no IntelliSense will ever help you ,
In what way will it not ever help you? Can't intellisense work with
aggregate initialization or list initialization in general? It should be
easy enough for it to figure out the possible overloads and, when you open
the first brace, list possibilities for designated or positional list
arguments.

Maybe such tools aren't not smart enough to do that at present, but I see
no reason why it would be impossible for them to provide help.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/0cdf7e4c-5116-43da-b75d-566d8ddaaf03%40isocpp.org.
Zhihao Yuan
2018-08-16 16:52:36 UTC
Permalink
Sent: Thursday, August 16, 2018 10:42 AM
foo({.x = 5, .y = 12});
foo({5, 12});
foo({.x = 5, 12}); //ill-formed
This may be extended to at least allow
an _initializer-list_ as a prefix.
complex a({.r = 5.0d, .i = 3.0d});
complex b({.r = 4.2d, .theta_rad = 2});
This is deliberately not allowed.
And while you can forward them, the forwarding function only sees it as a single struct, not a set of values.
Some authors believe that if we get some form of
named parameters in the future, its semantics
should be equivalent to decomposing such a struct
with a compiler synthesized structured binding.
--
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 mailto:std-proposals+***@isocpp.org.
To post to this group, send email to mailto:std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/5d064165-5a58-4810-90f7-aa3732be92db%40isocpp.org?utm_medium=email&utm_source=footer.
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/LrF6Q76BEAfOcjp9qD7wnpqpOSG9hUtw-QqCCfhhKWheMaHfglhF1jISPN_6xkSC4bnSC139Vz-86qLpesfUDWKeObbgle4RZSmE6Eaj9kA%3D%40miator.net.
Matthew Woehlke
2018-08-23 20:26:58 UTC
Permalink
(Sorry, I'm only just now reading the original post...)
Post by Justin Bassett
However, I believe that the name should be part of the function type and
should be mangled into the name for the function. It should not be allowed
int foo(int .x, int .y);
int foo(int .a, int .b);
If the name of the parameters are not part of the function, then if those
declarations are in separate translation units, there's little way to
enforce that this should fail to compile / link.
If the name is part of the ABI, *why* should the above be forbidden? For
that matter, *how* would you forbid it? They have different mangled names...

If the two exist only in separate TU's and are never seen in the same
TU, you would be requiring the *linker*, not the compiler, to reject this.
Post by Justin Bassett
This does bring in the issue that it becomes harder to change existing APIs
to accept named parameters in an ABI compatible manner.
FWIW, my current thought is to solve this by means of an explicitly
inline trampoline function. (Actually, I would ideally make it an
*alias*, not a "real" trampoline at all.)

For example:

void foo(int);
using foo(int .x) = foo(int);

Basically, it is a mechanism to add a function prototype to the overload
set, such that the added overload actually resolves to a different ABI
function. Thus, you can write code *as if* `foo(int .x)` existed, but
when the compiler resolves a call to the named argument version, it will
*actually* call `foo(int)`. This allows the ABI to be unchanged.
Post by Justin Bassett
Now for templates. In order to have higher-order functions which work on
named parameters, I believe it is necessary to have a new kind of template
// I separated the name completely from the type.
// This would severely complicate generic code, however, so maybe there's
// a way to keep both together
template <typename F, .typename Name, typename Arg>
void call(F fn, Arg&& .Name arg) {
// Some syntax to expand the name is needed. I'm not sure what
// a reasonable choice is. There should also probably be a way
// to generate a name from a compile time string.
fn(.(Name) = std::forward<Arg>(arg));
}
...which suggests that e.g. std::invoke can't use named parameters. I
don't think that will work.
Post by Justin Bassett
Reflection could possibly allow us to inspect the actual name supplied
(useful for libraries such as fmt: fmt::format("({x}, {y})", .x = 10, .y =
20); ), and it would probably be useful to be able to generate a name from
a compile-time string.
I've been thinking along the lines of named parameters being syntax
sugar for something like `std::arg<T, name>`, where `name` is a string
literal type. So reflection would just see the std::arg, and we don't
have to think about this too hard (or about ABI).

(Not *just* syntax sugar; they affect overload resolution also. But for
e.g. reflection, they'd just be sugar.)

I *think* this makes your above example possible, though it may require
something like building a dictionary by converting the compile-time
literals into (possibly) run-time keys.
Post by Justin Bassett
Further ideas: I don't want to propose this yet, but I would also like to
see named parameters in template parameters. For example, it would be nice
std::unordered_map<Key,
Value, .allocator = MyAllocator> . I believe this would break ABI
compatibility, though.
I think this is an orthogonal space, much closer actually to designated
initializers. (Yes, it *looks* very much the same to users, but
implementation-wise I don't think it has anything like the same sorts of
problems as genuine named *function arguments*.)

This would be a good space for an independent proposal to explore.
--
Matthew
--
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+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/2bb46dc4-a92b-c85c-0a37-9c09bb20b800%40gmail.com.
Loading...