C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Explicitly specifying default arguments

From: Jason McKesson <jmckesson_at_[hidden]>
Date: Wed, 1 Feb 2023 20:24:32 -0500
On Wed, Feb 1, 2023 at 10:39 AM Andrey Semashev via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> On 2/1/23 17:25, Bo Persson via Std-Proposals wrote:
> > On 2023-02-01 at 14:22, Andrey Semashev via Std-Proposals wrote:
> >> On 2/1/23 16:19, Bo Persson via Std-Proposals wrote:
> >>> On 2023-02-01 at 13:56, Andrey Semashev via Std-Proposals wrote:
> >>>> Hi,
> >>>>
> >>>> Would it be possible to be able to explicitly specify default arguments
> >>>> for template specializations and function calls?
> >>>>
> >>>> void foo(int x, int y = 10, int z = 20);
> >>>>
> >>>> foo(1, default, 3); // == foo(1, 10, 3);
> >>>>
> >>>>
> >>>> // Use default ordering function
> >>>> typedef std::set< int, default, my_alloc > my_set;
> >>>>
> >>>> // Use default compare and hash functions
> >>>> typedef std::unordered_set< int, default, default, my_alloc >
> >>>> my_uset;
> >>>>
> >>>>
> >>>> template<
> >>>> typename T,
> >>>> typename = whatever,
> >>>> bool = is_special< T >::value
> >>>> >
> >>>> struct trait {};
> >>>>
> >>>> // Specialization: trait< T, whatever, true >
> >>>> template< typename T >
> >>>> struct trait< T, default, true > {};
> >>>>
> >>>> This syntax is currently invalid, so the extension would be pretty
> >>>> harmless. This would allow to avoid code duplication, where the user of
> >>>> the function or template, or the one who specializes the template, has
> >>>> to duplicate the default argument when he only needs to specify the
> >>>> arguments after that.
> >>>
> >>> This seems to have been proposed 20 years ago.
> >>>
> >>> https://wg21.link/N1466
> >>>
> >>> Didn't go anywhere.
> >>
> >> Any particular reason why it got rejected or it was simply abandoned?
> >>
> >
> > It's too long ago, I don't remember.
> >
> > One argument could be that there are several ways around the limitation.
> >
> > Like if the arguments are not all of the same type, you can have
> > overloads with fewer arguments that forwards to the full function.
>
> Obviously, this would complicate maintenance as you'd have to provide
> all permutations of the specified/not specified optional arguments.
> Remember when we didn't have perfect forwarding in the core language?

It's interesting that you bring up perfect forwarding. Because
forwarding pretty much kills this idea (and most forms of named
parameters.

That is, if you want `T t(1, default, 5);` to work, how do you propose
to make `optional<T> t(std::in_place, 1, default, 5);` work? Or better
yet, `std::thread thr(some_functor(), 1, default, 5);`?

The closest I could come up with is that the expression `default` is a
prvalue of some `nullptr_t`-style type. Values of this type can be
created, copied, stored, etc just like `nullptr_t`. But it is
otherwise inert; unable to be converted into any other type. Unless of
course you pass such a valueit as a parameter to a function; if that
function takes a default parameter, then it initializes the parameter
with the default value.

Which opens up a whole new can of worms regarding overload resolution
and function selection. Plus, there's the fact that "has a default
parameter" is not an innate property of a function; it's just
something that a particular declaration happens to have.

I would argue that if you cannot solve the forwarding problem for
default parameters, then you're basically un-perfecting perfect
forwarding (not that it's actually perfect as is, but it's not nearly
this bad). And that's not worth the gains of being able to default
parameters.

Received on 2023-02-02 01:25:09