2

I want to do something like this in a well-defined manner:

struct S { static some_integral_type f() noexcept { return some_cast<...>(&f); } }; 

The integer can be signed or unsigned. The result should be the same as the casts of object pointers to uintptr_t or intptr_t produce. AFAIK casts to those are not guaranteed to be possible for function pointers. Even casts to uintmax_t and intmax_t might not work for all I know.

I need this so I can produce a unique "handle" from a function pointer, that I can then use in a switch statement.

10
  • 1
    What should the resulting integer be? The memory address? Commented Nov 7, 2015 at 20:34
  • 4
    Sounds like a XY problem. What do want to actually achieve? Commented Nov 7, 2015 at 20:35
  • 1
    If you really have to do this, at least use (u)intptr_t to avoid any data loss. Commented Nov 7, 2015 at 20:39
  • 2
    @zenith yes, but function and member function pointers are not object pointers. Commented Nov 7, 2015 at 20:39
  • 2
    That answer is wrong and irrelevant. Commented Nov 7, 2015 at 20:56

3 Answers 3

4

In general, no.

First, member-function-pointers (and member-pointers) are hairy beasts the standard says very little about.
So, let's ignore them for now.

Next, it might not even be possible to round-trip plain old function-pointers through void*, and the standard only defines a type for round-tripping data-pointers through integers, if the implementation supports such:
(u)intptr_t.

Naturally, if your implementation has a large enough integer-type, you can manually do it by reading the pointer as an unsigned char[] and combining it to a single numeric value, the operation then being reversible.

Be aware that equal function-pointers can result in different numbers if you go that route though, as the same pointer can have multiple possible representations (for example padding bytes, non-value-bits, segmentation)...

Sign up to request clarification or add additional context in comments.

4 Comments

Be aware that equal function-pointers can result in different numbers if you go that route though... Why?
@user1095108: Well, let's go to x86, segmented memory as an example: There can be multiple ways to refer to the same function, with different segment-offset-pairs. Also, there might be padding in it (32bit-offset, 16bit-segment, 2 Byte padding).
On POSIX-compliant systems you're guaranteed to be able to convert a function pointer to a void pointer; and vice versa
@Deduplicator check my nonstandard solution please.
1

You can attempt to select an integer of the same size as the function pointer with a metafunction- the required size being sizeof(void(*)()). However, there's no guarantee that any such integer type exists.

Realistically speaking, casting it to void* or intptr_t is gonna work on pretty much all the mainstream platforms.

3 Comments

I could just try with intmax_t or uintmax_t then. If those don't work, nothing will.
@user1095108: Actually, some compilers support integers bigger than intmax_t, as they couldn't change the latter due to ABI-compatibility.
@Deduplicator How about unsigned long long and long long then?
0

Taken from Can std::hash be used to hash function pointers?

In a previous attempt I attempted to cast the function pointer to void*, which isn't allowed and doesn't compile (see: https://isocpp.org/wiki/faq/pointers-to-members#cant-cvt-memfnptr-to-voidptr for details). The reason is that a void* is a data pointer, while a function pointer is a code pointer.

2 Comments

I'm not looking for a hash, as those can collide. That is, 2 different function pointers might produce the same hash.
Since you can do equality checks with member function pointers, that should not be the problem. See stackoverflow.com/questions/1328238/… for more info.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.