C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Explicitly specifying default arguments

From: Andrey Semashev <andrey.semashev_at_[hidden]>
Date: Wed, 1 Feb 2023 18:39:41 +0300
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?

> You could change the order, so the "most defaulted" argument appears
> last (reduces the number of time "default" would be useful).

This is possible, although not always, because there may not be a clear
"most likely default" argument. Also, there are stable interfaces that
one cannot change (e.g. a third party library that you have no control
over).

> Nowadays you could also pass a struct and name the arguments, like
>
> f({.x = 1, .z = 3});

This requires a completely different interface of f that takes a struct
instead of distinct arguments. Besides the maintenance burden, I'm
pretty sure that interface is not as efficient in run time (firstly, it
mandates binary layout of the whole argument pack; secondly, it may not
be passed in registers when distinct arguments would).

In any case, my proposal is not about named arguments, it's about
simplifying passing the defaults, that's it.

> So how many use cases are there left to motivate a language change?

The std::map/set & co. are the ones I stumble upon regularly. And every
time I wish I didn't have to include <functional> and type the functions
manually. The trait example also looks interesting to me.

Received on 2023-02-01 15:39:54