C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Implicitly accepting leading default function/template argument values

From: David Jones <davidjones1105_at_[hidden]>
Date: Sun, 6 Mar 2022 16:17:35 +0000
​Under your proposal, it would have to mean the same as "x = f(1, 2, /*some defaulted thing*/)".
Under my proposal, "x = f(1,2,)" and "x = f(1,2)" would be identical, as long is f is a function with default values supplied for every argument after the second.

By the way, how would that even work, with overload resolution?
Identically to how the current rules work when trailing default arguments are left out.

Look at how std::pmr::set<int> does it, and consider writing your own my::allocated_set<int> along the same lines.
Nobody is going to write a template class every time they don't want to have to copy out a default template argument. I can have the compiler fill in the last default template argument for me by simply leaving it out, why not the second-to-last default template argument?

David
________________________________
From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Sent: 06 March 2022 15:54
To: Std-Proposals <std-proposals_at_lists.isocpp.org>
Cc: David Jones <davidjones1105_at_hotmail.co.uk>
Subject: Re: [std-proposals] Implicitly accepting leading default function/template argument values

On Sun, Mar 6, 2022 at 10:26 AM David Jones via Std-Proposals <std-proposals_at_[hidden]<mailto:std-proposals_at_[hidden]>> wrote:
Consider the function

void foo(int i = 1, int j = 2, int k = 3);

Trailing default argument values can be accepted implicitly by simply skipping them in the function call:

foo(); //Accept default values for i, j, and k
foo(1); //Accept default values for j and k, supply value for i
foo(1,2); //Accept default value for k, supply values for i and j

But to my knowledge, there is no method for implicitly accepting leading default argument values - they must be copied out explicitly:

foo(1,2,5); //Accept default values for i and j by copying them out explicitly, supply value for k

I suggest that this could be done implicitly thus:

foo(,,2); //Accept default values for i and j, supply value for k
foo(,1); //Accept default values for i and k, supply value for j

That would close the door on the vastly vastly more useful Python-style syntax
    x = f(
        1,
        2,
    )
which in C++ today means "syntax error," but in Python and other modern languages means the same as "x = f(1, 2)".
Under your proposal, it would have to mean the same as "x = f(1, 2, /*some defaulted thing*/)".

By the way, how would that even work, with overload resolution? I guess you're picturing something kind of like what `f<>(1, 2)` does today — f<> says "I'd like to call a function f that can take two ints, but btw, please only consider fs that are template instantiations, not ordinary functions." So `f(1,2,)` would say "I'd like to call a function f that can take two ints, but btw, please only consider fs that also contain at least one defaulted argument after the first two." The f<> quirk is pretty awful IMHO, and I would not like to see any new similar quirks in that area. So also for that reason, your proposal is a bad one.


This could also apply to default template arguments. For example, to specify a custom allocator for std::set the comparison type must currently also be explicitly specified :

std::set<int, std::less<int>, Myalloc>; //OK, but std::less<int> is superfluous.
std::set<int,, Myalloc>; //Currently an error

Look at how std::pmr::set<int> does it, and consider writing your own my::allocated_set<int> along the same lines.

–Arthur

Received on 2022-03-06 16:17:38