C++ Logo

std-discussion

Advanced search

Re: Guarantees over addresses from function pointers created from lambda

From: Tiago Freire <tmiguelf_at_[hidden]>
Date: Mon, 28 Apr 2025 08:25:52 +0000
> > 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?
> Attributes can be ignored.
> The correctness of a program should not rely on something that can be ignored.

Make it a key word, make the concept of attribute like things that can't be ignored.

> get1/get2/get3 might generate the same code, but it is not possible to use one instead of another.

Functions addresses are a thing that is defined after linkage. At that point most of the language constructs don't really exist.
I don't know what it means to be "identical" without it being able to replace one by the other without the ability of not being able to tell the difference.
Baring the exception of using the position of the code as an input to execution, If it generates the exact same code, it must do the exact same thing.



-----Original Message-----
From: Std-Discussion <std-discussion-bounces_at_[hidden]cpp.org> On Behalf Of Federico Kircheis via Std-Discussion
Sent: Monday, April 28, 2025 9:32 AM
To: std-discussion_at_lists.isocpp.org
Cc: Federico Kircheis <federico_at_kircheis.it>
Subject: Re: [std-discussion] Guarantees over addresses from function pointers created from lambda

On 28/04/2025 7:56 am, Tiago Freire via Std-Discussion wrote:
> 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.


If anyone has a suggestion how the concrete example I have provided can be improved, I'm all ears.

But the problem appears in other context too:

struct T{int i;};
T* get1(void* ptr){ return start_lifetime_as<T>(ptr);}
T* get2(void* ptr){ return reinterpret_cast<T>(ptr);}
T* get3(void* ptr){ return std::launder(reinterpret_cast<T>(ptr));}


get1/get2/get3 might generate the same code, but it is not possible to use one instead of another.

> 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?

Attributes can be ignored.
The correctness of a program should not rely on something that can be ignored.

> *From:*Tom Honermann <tom_at_[hidden]>
> *Sent:* Monday, April 28, 2025 6:08 AM
> *To:* std-discussion_at_lists.isocpp.org
> *Cc:* Tiago Freire <tmiguelf_at_hotmail.com>
> *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_lists.isocpp.org>
> <mailto:std-discussion-bounces_at_[hidden]p.org> on behalf of
> Jennifier Burnett via Std-Discussion <std-
> discussion_at_[hidden]> <mailto:std-discussion_at_lists.isocpp.org>
> *Sent:* Sunday, April 27, 2025 12:06:36 PM
> *To:* std-discussion_at_lists.isocpp.org <mailto:std-
> discussion_at_[hidden]p.org> <std-discussion_at_lists.isocpp.org>
> <mailto:std-discussion_at_lists.isocpp.org>; Nate Eldredge via Std-
> Discussion <std-discussion_at_[hidden]> <mailto:std-
> discussion_at_[hidden]>
> *Cc:* Jennifier Burnett <jenni_at_jburnett.me.uk>
> <mailto:jenni_at_jburnett.me.uk>
> *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]p.org> <mailto:std-
> discussion_at_[hidden]g> 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 <std::variant> or some other way. So I wonder
> if anyone has studied the impact on existing code bases of
> dropping this guarantee.
>
>
>
>

--
Std-Discussion mailing list
Std-Discussion_at_lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion

Received on 2025-04-28 08:25:55