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
There should be some way to specify that the parameter is name-only. For example, altering Python's implementation:// anything after the . is name-onlyint foo(., int .x);Default arguments should be able to work as they are now.
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.
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:
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.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAPuuy5eBx1ybcPjS6dNsk7n1_c2uhdRBS19qr%3Dq5cj3cTURnLQ%40mail.gmail.com.
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 example, altering Python's implementation:// anything after the . is name-onlyint 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 argumentNow 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 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.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?).
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: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 1f(.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 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).
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))
template<class T>
void copy(T.from a, T&.to b) {
b = a;
}
On 2018-08-16 07:53, David Brown wrote:
> 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*.
- no IntelliSense will ever help you ,
On 2018-08-16 10:53, David Brown wrote:
> On 16/08/18 16:34, Matthew Woehlke wrote:
>> 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.
--
Matthew
On 2018-08-16 14:40, mihailn...@gmail.com wrote:
> 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.
> 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
On Thursday, August 16, 2018 at 9:49:30 PM UTC+3, Matthew Woehlke wrote:On 2018-08-16 14:40, mihailn...@gmail.com wrote:
> 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.
> 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.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)
Can this be solved by types - only if workaround is solvingCan 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".
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.htmlThe latter did not pass and is turned into the poor-mans http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2018/p0671r2.htmlIn other words, you should state what is different.
On 2018-08-16 07:53, David Brown wrote:
> 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*.
Let's add a syntax for /required/ named parameters.
On Thursday, 16 August 2018 07:53:47 PDT David Brown wrote: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@@YAXH@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.
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
* 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.
foo(int :a, int :b = 3, int :c = 12);
foo(1, c: 6); // name *must* be used here because 'b' is omitted
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 solvingCan 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.
On 17/08/18 17:16, Matthew Woehlke wrote:
> On 2018-08-17 06:14, David Brown wrote:
>> On 16/08/18 15:08, mihailn...@gmail.com wrote:
>>> 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:".)
On 2018-08-17 00:04, Justin Bassett wrote:
> 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.
So what?
void foo(int, double=1.);
void foo(int, int=2);
foo(1); // error: ambiguous
> Overloading on name-only parameters is just fine.
What is a "name only" parameter?
On 2018-08-17 12:17, Jake Arkinstall wrote:
> On Fri, 17 Aug 2018, 16:16 Matthew Woehlke wrote:
>> 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 :-).)
> 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.
I would not allow skipping for unnamed parameters.
template < RectLeftTop Rect > // Concept RectLeftTopvoid 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-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUb_iJ8B%3DELuJgBVo-R3fvPPOcgjMobr_4hvEQSR2%3DoALQ%40mail.gmail.com.
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.
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.
Vicente
Vicente
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.
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.
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
On Sunday, August 19, 2018 at 5:21:11 PM UTC-4, Vicente J. Botet Escriba wrote:Le 19/08/2018 à 19:22, mihailn...@gmail.com a écrit :
I would like to see the two features proposed independently.
On Sunday, August 19, 2018 at 7:46:58 PM UTC+3, Vicente J. Botet Escriba wrote:Le 19/08/2018 à 15:04, mihailn...@gmail.com a écrit :
I'm not sure yet we need some syntactic sugar for this tag dispatching feature neither.
On Sunday, August 19, 2018 at 3:26:12 PM UTC+3, Vicente J. Botet Escriba wrote: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 back: 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 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 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.
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.
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.
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.
On Sunday, August 19, 2018 at 5:21:11 PM UTC-4, Vicente J. Botet Escriba wrote:Le 19/08/2018 à 19:22, mihailn...@gmail.com a écrit :
I would like to see the two features proposed independently.
On Sunday, August 19, 2018 at 7:46:58 PM UTC+3, Vicente J. Botet Escriba wrote:Le 19/08/2018 à 15:04, mihailn...@gmail.com a écrit :
I'm not sure yet we need some syntactic sugar for this tag dispatching feature neither.
On Sunday, August 19, 2018 at 3:26:12 PM UTC+3, Vicente J. Botet Escriba wrote: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 back: 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 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 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.
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 :(
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.
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.
Vicente
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.
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 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.
IMHO, this case is covered by weak named parameters already.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.
"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.
On Monday, August 20, 2018 at 6:37:39 PM UTC+3, Nicol Bolas wrote:
On Monday, August 20, 2018 at 2:15:17 AM UTC-4, Vicente J. Botet Escriba wrote:
Le 19/08/2018 à 23:53, Nicol Bolas a écrit :
On Sunday, August 19, 2018 at 5:21:11 PM UTC-4, Vicente J. Botet Escriba wrote:
Le 19/08/2018 à 19:22, mihailn...@gmail.com a écrit :
On Sunday, August 19, 2018 at 7:46:58 PM UTC+3, Vicente J. Botet Escriba wrote:Le 19/08/2018 à 15:04, mihailn...@gmail.com a écrit :
I'm not sure yet we need some syntactic sugar for this tag dispatching feature neither.
On Sunday, August 19, 2018 at 3:26:12 PM UTC+3, Vicente J. Botet Escriba wrote: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 back: 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 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.
...
IMHO, this case is covered by weak named parameters already.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.
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.
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.
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 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.
So, you can't be against one part of a proposal? The standards committee does it all the time.
IMHO, this case is covered by weak named parameters already.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.
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.
"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.
Also, this obviously does not address the named arguments, that are optional, the "weak" ones, so this solution will not make everyone happy.
//weak argument names, not mandatory
...
//strong argument name, adds an overload, not ignorable
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.
On Monday, August 20, 2018 at 4:18:34 PM UTC-4, mihailn...@gmail.com wrote:On Monday, August 20, 2018 at 9:45:02 PM UTC+3, Nicol Bolas wrote:On Monday, August 20, 2018 at 12:20:20 PM UTC-4, mihailn...@gmail.com wrote: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.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:Also, this obviously does not address the named arguments, that are optional, the "weak" ones, so this solution will not make everyone happy.Emphasis added. And there's this post://weak argument names, not mandatory...//strong argument name, adds an overload, not ignorableYes, 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 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.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".
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.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); //< errorauto child(name mutter, vater); //< OKauto 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.