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.

user1095108
  • 14,119
  • 9
  • 58
  • 116

3 Answers3

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)...

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
  • Be aware that equal function-pointers can result in different numbers if you go that route though... Why? – user1095108 Nov 07 '15 at 20:54
  • @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). – Deduplicator Nov 07 '15 at 20:59
  • 1
    On POSIX-compliant systems you're guaranteed to be able to convert a function pointer to a void pointer; and vice versa – RamblingMad Nov 08 '15 at 15:20
  • @Deduplicator check my nonstandard solution please. – user1095108 Nov 08 '15 at 15:23
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.

Puppy
  • 144,682
  • 38
  • 256
  • 465
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.

Community
  • 1
  • 1
Christopher Oezbek
  • 23,994
  • 6
  • 61
  • 85
  • I'm not looking for a hash, as those can collide. That is, 2 different function pointers might produce the same hash. – user1095108 Nov 07 '15 at 20:49
  • Since you can do equality checks with member function pointers, that should not be the problem. See http://stackoverflow.com/questions/1328238/how-to-hash-and-compare-a-pointer-to-member-function for more info. – Christopher Oezbek Nov 07 '15 at 20:54