Date: Sun, 4 Jan 2026 11:11:15 -0500
On Sun, Jan 4, 2026 at 10:15 AM Jan Schultke via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> I think the evil of needing the explicit opt-in significantly outweighs the perceived freedom it gives library authors. Note that as I've already mentioned, there are numerous properties of functions that the user can observe but which are likely implementation details, such as:
>
> recursive leakage through headers
> expression validity tests / SFINAE stability
> ability to form function pointers and function references
> ability to pass template arguments explicitly, especially cv-qualified types
> any property only obtainable through reflection (such as parameter names)
> lack or existence of default function arguments
> lack or existence of default template arguments
> distinct declaration vs using-declaration of an existing global entity
> various type choices, like using iterators as pointers
> existence of a noexcept specification or lack thereof
>
> Sometimes these are stable, but very often it's not intended for users to rely on them. This has been the status quo of the last 30 years, and people talk about adding function parameter names to this list as if it was obviously unacceptable, but it really isn't.
Well, let's break that list down into what I feel is the most
important part: If you change it, is it still the same function?
That is, if I have a declaration X, and a declaration Y, if those two
differ in one of the ways you've outlined, do X and Y denote the same
entity?
Some things on your list don't declare a different entity. Default
arguments don't make the entity different. But most of the ones on
your list do denote different entities. If you change a non-template
function into a template function, that *is* a fundamentally different
entity. Changing the types of function arguments creates a different
entity. Etc.
I think it's wrong to consider changes that fundamentally create a
different kind of entity to be "implementation details". You can think
of them that way if you like, but as far as the language itself is
concerned, those are different entities.
When the writer of a library has written their interface a certain
way, whether they intended to or not, they have formed a contract
between themselves and the caller that the interface may not be
changed in any way that would represent a change in that entity. Or if
they do change it, this constitutes a breaking change even if nobody
actually gets broken by it.
The C++ standard has rules about how standard library interfaces are
allowed to be written to permit a certain amount of variance in terms
of implementations (particularly of overload sets). But unless that
kind of rule is a part of the documentation of the library in
question, the way you write a function is baked into that interface.
So to me, the question of explicit vs. non-explicit syntax ultimately
boils down to this: do you want named parameters to be a property of
the function entity or not? Are they ephemeral like default arguments,
changeable with declarations and thus are mere suggestions, or are
they real pieces of syntax that are a part of the entity?
Consider reflection. Reflection reflects over entities, not
declarations. Because default arguments are part of a function
declaration, reflection cannot interact with them in any way. Do you
want named parameters to work like that too? Because without an opt-in
syntax, they aren't something you can reflect over.
To me, making default arguments ephemeral was a mistake. They *should
have been* a property of the entity, and the fact that they aren't
makes the language more annoying to use. This is born out in
reflection where you cannot reflectively call a function with a
default argument.
This is not a mistake we should repeat.
> On the other hand, the ability to rely on function parameter names is not really a problem in practice in languages with support for named arguments, like Kotlin.
I'm not familiar with Kotlin, but most of the languages I'm familiar
with that have named arguments treat them as a fundamental,
unchangeable property of that entity. As fundamental a property of an
entity as its parameter list.
> It's only conjectured to be a major problem in C++. However, an explicit opt-in would require every library author to do significant work to permit passing named function arguments, and this work isn't exactly clean and easy. Except for fresh C++29-only codebases, this would devolve into code looking like:
>
> f(int x, int y);
> f(
> int MY_LIB_NAMED_SINCE_CXX29(x),
> int MY_LIB_NAMED_SINCE_CXX29(x)
> );
>
> I don't want to see every code base looking like this for the next 10-20 years, or authors understandably not bothering with named parameters because this looks disgusting. There could still be a per-function opt-in rather than a per-parameter opt-in, but I'm not sure if that's worth the trouble.
>
> On Sun, 4 Jan 2026 at 15:42, Sebastian Wittmeier via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>
>> Parameter names are optional in function declarations. (And can be named differently from their counterpart in definitions.)
>>
>> So far they were either
>>
>> - kept the same between declaration and definition -> leak of internal (implementation) data
>>
>> - used as reminder for the programmer or for popups and autocompletes in IDEs; possibly also for compile error messages
>>
>>
>>
>> So the programmer already has a lot of flexibility. Nevertheless you are right, that the parameter names of included functions never leaked into the caller code up till now.
>>
>>
>>
>>
>> -----Ursprüngliche Nachricht-----
>> Von: Barry Revzin via Std-Proposals <std-proposals_at_[hidden]>
>> Gesendet: So 04.01.2026 15:13
>> Betreff: Re: [std-proposals] Labelled parameters
>> An: std-proposals_at_[hidden];
>> CC: Barry Revzin <barry.revzin_at_[hidden]>;
>>
>> Even when the parameter names are normal-ish, that's probably not something that library authors want users to rely on. For instance, in range-v3, the predicates and projections are pretty consistently named pred and proj, but is that the correct user-facing name? Eric and Casey have never had to think about this before. max(r, .proj=key) is definitely nicer to read than max(r, {}, key), but not as nice as max(r, .key=key) (or ".by" or something else). Lack of explicit opt-in cements a decision that up until now was never even a known decision.
>>
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
<std-proposals_at_[hidden]> wrote:
>
> I think the evil of needing the explicit opt-in significantly outweighs the perceived freedom it gives library authors. Note that as I've already mentioned, there are numerous properties of functions that the user can observe but which are likely implementation details, such as:
>
> recursive leakage through headers
> expression validity tests / SFINAE stability
> ability to form function pointers and function references
> ability to pass template arguments explicitly, especially cv-qualified types
> any property only obtainable through reflection (such as parameter names)
> lack or existence of default function arguments
> lack or existence of default template arguments
> distinct declaration vs using-declaration of an existing global entity
> various type choices, like using iterators as pointers
> existence of a noexcept specification or lack thereof
>
> Sometimes these are stable, but very often it's not intended for users to rely on them. This has been the status quo of the last 30 years, and people talk about adding function parameter names to this list as if it was obviously unacceptable, but it really isn't.
Well, let's break that list down into what I feel is the most
important part: If you change it, is it still the same function?
That is, if I have a declaration X, and a declaration Y, if those two
differ in one of the ways you've outlined, do X and Y denote the same
entity?
Some things on your list don't declare a different entity. Default
arguments don't make the entity different. But most of the ones on
your list do denote different entities. If you change a non-template
function into a template function, that *is* a fundamentally different
entity. Changing the types of function arguments creates a different
entity. Etc.
I think it's wrong to consider changes that fundamentally create a
different kind of entity to be "implementation details". You can think
of them that way if you like, but as far as the language itself is
concerned, those are different entities.
When the writer of a library has written their interface a certain
way, whether they intended to or not, they have formed a contract
between themselves and the caller that the interface may not be
changed in any way that would represent a change in that entity. Or if
they do change it, this constitutes a breaking change even if nobody
actually gets broken by it.
The C++ standard has rules about how standard library interfaces are
allowed to be written to permit a certain amount of variance in terms
of implementations (particularly of overload sets). But unless that
kind of rule is a part of the documentation of the library in
question, the way you write a function is baked into that interface.
So to me, the question of explicit vs. non-explicit syntax ultimately
boils down to this: do you want named parameters to be a property of
the function entity or not? Are they ephemeral like default arguments,
changeable with declarations and thus are mere suggestions, or are
they real pieces of syntax that are a part of the entity?
Consider reflection. Reflection reflects over entities, not
declarations. Because default arguments are part of a function
declaration, reflection cannot interact with them in any way. Do you
want named parameters to work like that too? Because without an opt-in
syntax, they aren't something you can reflect over.
To me, making default arguments ephemeral was a mistake. They *should
have been* a property of the entity, and the fact that they aren't
makes the language more annoying to use. This is born out in
reflection where you cannot reflectively call a function with a
default argument.
This is not a mistake we should repeat.
> On the other hand, the ability to rely on function parameter names is not really a problem in practice in languages with support for named arguments, like Kotlin.
I'm not familiar with Kotlin, but most of the languages I'm familiar
with that have named arguments treat them as a fundamental,
unchangeable property of that entity. As fundamental a property of an
entity as its parameter list.
> It's only conjectured to be a major problem in C++. However, an explicit opt-in would require every library author to do significant work to permit passing named function arguments, and this work isn't exactly clean and easy. Except for fresh C++29-only codebases, this would devolve into code looking like:
>
> f(int x, int y);
> f(
> int MY_LIB_NAMED_SINCE_CXX29(x),
> int MY_LIB_NAMED_SINCE_CXX29(x)
> );
>
> I don't want to see every code base looking like this for the next 10-20 years, or authors understandably not bothering with named parameters because this looks disgusting. There could still be a per-function opt-in rather than a per-parameter opt-in, but I'm not sure if that's worth the trouble.
>
> On Sun, 4 Jan 2026 at 15:42, Sebastian Wittmeier via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>
>> Parameter names are optional in function declarations. (And can be named differently from their counterpart in definitions.)
>>
>> So far they were either
>>
>> - kept the same between declaration and definition -> leak of internal (implementation) data
>>
>> - used as reminder for the programmer or for popups and autocompletes in IDEs; possibly also for compile error messages
>>
>>
>>
>> So the programmer already has a lot of flexibility. Nevertheless you are right, that the parameter names of included functions never leaked into the caller code up till now.
>>
>>
>>
>>
>> -----Ursprüngliche Nachricht-----
>> Von: Barry Revzin via Std-Proposals <std-proposals_at_[hidden]>
>> Gesendet: So 04.01.2026 15:13
>> Betreff: Re: [std-proposals] Labelled parameters
>> An: std-proposals_at_[hidden];
>> CC: Barry Revzin <barry.revzin_at_[hidden]>;
>>
>> Even when the parameter names are normal-ish, that's probably not something that library authors want users to rely on. For instance, in range-v3, the predicates and projections are pretty consistently named pred and proj, but is that the correct user-facing name? Eric and Casey have never had to think about this before. max(r, .proj=key) is definitely nicer to read than max(r, {}, key), but not as nice as max(r, .key=key) (or ".by" or something else). Lack of explicit opt-in cements a decision that up until now was never even a known decision.
>>
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2026-01-04 16:11:32
