Date: Mon, 28 Apr 2025 05:56:07 +0000
I’m not convinced by this example. I have written many callback systems and never has “uniqueness” been relevant.
Is that a good design? Or one that can’t be improved upon?
Had C++ not provided this guarantee all along, would the algorithm (in the context of its intended end use) be undesignable?
As mentioned, the only reason it would make a difference is because you are trying to do logic related to the function beyond “it exists, and it is callable”, and whatever that is there’s probably a better solution to be found elsewhere.
In this case, what you want is a unique token and absent a feature for that you used an unrelated “this function address is unique” to achieve that.
I’m not saying that maybe it isn’t necessary in this case, I don’t see the concrete example you might have in mind.
But if the address being unique is important for this function, wouldn’t it be better to explicit request it with a tag [[unique_address]] and not make it the default everywhere?
From: Tom Honermann <tom_at_[hidden]>
Sent: Monday, April 28, 2025 6:08 AM
To: std-discussion_at_[hidden]
Cc: Tiago Freire <tmiguelf_at_[hidden]>
Subject: Re: [std-discussion] Guarantees over addresses from function pointers created from lambda
On 4/27/25 6:53 AM, Tiago Freire via Std-Discussion wrote:
> I'm not sure how you could do that other than maybe dropping function pointer comparison altogether except against nullptr.
I don't see a reason not to do that.
Comparisons can be useful to support callback function registration systems. Designs that use the function pointer itself as the registration key depend on registered functions having exactly one unique address assigned to them.
Tom.
________________________________
From: Std-Discussion <std-discussion-bounces_at_[hidden]><mailto:std-discussion-bounces_at_[hidden]> on behalf of Jennifier Burnett via Std-Discussion <std-discussion_at_[hidden]><mailto:std-discussion_at_[hidden]>
Sent: Sunday, April 27, 2025 12:06:36 PM
To: std-discussion_at_[hidden]<mailto:std-discussion_at_[hidden]> <std-discussion_at_[hidden]><mailto:std-discussion_at_[hidden]>; Nate Eldredge via Std-Discussion <std-discussion_at_[hidden]><mailto:std-discussion_at_[hidden]>
Cc: Jennifier Burnett <jenni_at_[hidden]><mailto:jenni_at_[hidden]>
Subject: Re: [std-discussion] Guarantees over addresses from function pointers created from lambda
I have worked on one codebase that something did this, for basically the same reason as the original example in this thread where they were rolling their own vtables for a type erased callback storage class, and they used a sentinel function to identify trivially copyable and trivially destructible classes to skip the function call. Nullptr was used to indicate an empty callback.
In both cases there were branch mispredictions happening on the check for the sentinel (plus additional instructions were needed to form the sentinel address) and it was just faster to call an empty function for the trivial destructor and have the trivial copy just use a function that called memcpy. The original company as far as I'm aware didn't merge our changes back into their codebase.
I've also worked on a different codebase which was using a function pointer to a templated function as a form of cheap RTTI on a type erased container (games, so nobody ships codebases with it enabled).
Ideally if it was dropped you'd want existing code relying on it to break at compile time, I'm not sure how you could do that other than maybe dropping function pointer comparison altogether except against nullptr.
On 27 April 2025 03:49:37 BST, Nate Eldredge via Std-Discussion <std-discussion_at_[hidden]><mailto:std-discussion_at_[hidden]> wrote:
On Apr 26, 2025, at 11:34, Andrey Semashev via Std-Discussion <std-discussion_at_[hidden]><mailto:std-discussion_at_[hidden]> wrote:
The point is, even if the standard guarantees this [pointers to different functions comparing unequal], it's probably not a
good idea to rely on this in practice.
This being so, does anyone know if there has ever been a formal proposal to weaken this rule, or informal study of doing so?
I can certainly see the aesthetic argument for the rule, but I wonder how much real-life code actually relies on it. The only specific use case I can see is sentinels:
void sentinel() { }
void foo(void (*callback)()) {
if (!callback) {
proceed_without_callback();
} else if (callback == sentinel) {
something_special();
} else {
callback();
}
}
but it seems like a modern C++ programmer would rather do that with std::variant or some other way. So I wonder if anyone has studied the impact on existing code bases of dropping this guarantee.
Is that a good design? Or one that can’t be improved upon?
Had C++ not provided this guarantee all along, would the algorithm (in the context of its intended end use) be undesignable?
As mentioned, the only reason it would make a difference is because you are trying to do logic related to the function beyond “it exists, and it is callable”, and whatever that is there’s probably a better solution to be found elsewhere.
In this case, what you want is a unique token and absent a feature for that you used an unrelated “this function address is unique” to achieve that.
I’m not saying that maybe it isn’t necessary in this case, I don’t see the concrete example you might have in mind.
But if the address being unique is important for this function, wouldn’t it be better to explicit request it with a tag [[unique_address]] and not make it the default everywhere?
From: Tom Honermann <tom_at_[hidden]>
Sent: Monday, April 28, 2025 6:08 AM
To: std-discussion_at_[hidden]
Cc: Tiago Freire <tmiguelf_at_[hidden]>
Subject: Re: [std-discussion] Guarantees over addresses from function pointers created from lambda
On 4/27/25 6:53 AM, Tiago Freire via Std-Discussion wrote:
> I'm not sure how you could do that other than maybe dropping function pointer comparison altogether except against nullptr.
I don't see a reason not to do that.
Comparisons can be useful to support callback function registration systems. Designs that use the function pointer itself as the registration key depend on registered functions having exactly one unique address assigned to them.
Tom.
________________________________
From: Std-Discussion <std-discussion-bounces_at_[hidden]><mailto:std-discussion-bounces_at_[hidden]> on behalf of Jennifier Burnett via Std-Discussion <std-discussion_at_[hidden]><mailto:std-discussion_at_[hidden]>
Sent: Sunday, April 27, 2025 12:06:36 PM
To: std-discussion_at_[hidden]<mailto:std-discussion_at_[hidden]> <std-discussion_at_[hidden]><mailto:std-discussion_at_[hidden]>; Nate Eldredge via Std-Discussion <std-discussion_at_[hidden]><mailto:std-discussion_at_[hidden]>
Cc: Jennifier Burnett <jenni_at_[hidden]><mailto:jenni_at_[hidden]>
Subject: Re: [std-discussion] Guarantees over addresses from function pointers created from lambda
I have worked on one codebase that something did this, for basically the same reason as the original example in this thread where they were rolling their own vtables for a type erased callback storage class, and they used a sentinel function to identify trivially copyable and trivially destructible classes to skip the function call. Nullptr was used to indicate an empty callback.
In both cases there were branch mispredictions happening on the check for the sentinel (plus additional instructions were needed to form the sentinel address) and it was just faster to call an empty function for the trivial destructor and have the trivial copy just use a function that called memcpy. The original company as far as I'm aware didn't merge our changes back into their codebase.
I've also worked on a different codebase which was using a function pointer to a templated function as a form of cheap RTTI on a type erased container (games, so nobody ships codebases with it enabled).
Ideally if it was dropped you'd want existing code relying on it to break at compile time, I'm not sure how you could do that other than maybe dropping function pointer comparison altogether except against nullptr.
On 27 April 2025 03:49:37 BST, Nate Eldredge via Std-Discussion <std-discussion_at_[hidden]><mailto:std-discussion_at_[hidden]> wrote:
On Apr 26, 2025, at 11:34, Andrey Semashev via Std-Discussion <std-discussion_at_[hidden]><mailto:std-discussion_at_[hidden]> wrote:
The point is, even if the standard guarantees this [pointers to different functions comparing unequal], it's probably not a
good idea to rely on this in practice.
This being so, does anyone know if there has ever been a formal proposal to weaken this rule, or informal study of doing so?
I can certainly see the aesthetic argument for the rule, but I wonder how much real-life code actually relies on it. The only specific use case I can see is sentinels:
void sentinel() { }
void foo(void (*callback)()) {
if (!callback) {
proceed_without_callback();
} else if (callback == sentinel) {
something_special();
} else {
callback();
}
}
but it seems like a modern C++ programmer would rather do that with std::variant or some other way. So I wonder if anyone has studied the impact on existing code bases of dropping this guarantee.
Received on 2025-04-28 05:56:18