-2

This article lists all the different categories of pointers. I have tested the explicit conversion of different types of pointers to const void* in the following snippet (live):

#include <print> int var {}; void foo() { } struct Bar { char mem; void func() { } }; Bar b {}; int main() { // nullptr std::println( "{}", static_cast<const void*>( nullptr ) ); // pointer to object std::println( "{}", static_cast<const void*>( &var ) ); // pointer to function std::println( "{}", reinterpret_cast<const void*>( &foo ) ); // pointer to member variable std::println( "{}", static_cast<const void*>( &Bar::mem ) ); // doesn't compile std::println( "{}", static_cast<const void*>( &(b.mem) ) ); std::println( "{}", static_cast<const void*>( &(b.*(&Bar::mem)) ) ); // pointer to member function std::println( "{}", reinterpret_cast<const void*>( &Bar::func ) ); // compiles with a warning std::println( "{}", reinterpret_cast<const void*>( &(b.func) ) ); // doesn't compile std::println( "{}", reinterpret_cast<const void*>( &(b.*(&Bar::func)) ) ); // doesn't compile // Did I miss any other category? } 

Now I have a few questions:

  1. I want to know why static_cast<const void*>( &Bar::mem ) ); does not compile (since &(b.*(&Bar::mem)) does). The compiler says:
error: invalid 'static_cast' from type 'char Bar::*' to type 'const void*' 
  1. Also I want to know why it's not allowed to take the address of member functions (as seen in the last three statements). The compiler says:
ISO C++ forbids taking the address of a bound member function to form a pointer to member function. Say '&Bar::func' 
  1. Finally, which pointer types are we allowed to take (at least for trivial tasks like printing) without invoking errors or UB? It seems to me that pointer to member function is not allowed.
10
  • 1
    in static_cast<const void*>( &Bar::mem ) ) its not getting the function pointer that fails, but the cast to const void* Commented Jan 12, 2024 at 20:55
  • 2
    please one question per question. Commented Jan 12, 2024 at 20:56
  • 1
    You should think of &Bar::mem as specifying a class offset. It doesn't point to any specific object. Commented Jan 12, 2024 at 21:04
  • 2
    Generally speaking, pointers to data can be stored in a void*; pointers to functions cannot (portably). Commented Jan 12, 2024 at 21:12
  • 1
    Are pointers to non-static member function "formally" not considered pointers Commented Jan 13, 2024 at 2:47

1 Answer 1

2

A pointer to member is different from other pointers. It's not bound to a specific instance, but it's rather an offset into a class. Given an instance you can use a pointer to member to get the member. Casting it to void* is of no great use, hence C++ does not allow it. Generally C++ is less permissive than C concerning casts to void*. Hence, static_cast<const void*>( &Bar::mem ) ); does not compile.

On the other hand (b.*(&Bar::mem) uses the instance and the pointer to member to get a reference to the member mem of b. And &(b.*(&Bar::mem) is just the same as &(b.mem). Its a pointer to b.mem, a char*. You can cast char* to void*.

(2) and (3) is just about how the syntax is defined.

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

3 Comments

This means to get a real pointer to a member variable we need to have an instance of that type. On the other hand, taking the address of a member function is not allowed with/without an instance of the type. The rest of the cases are legal. Am I correct?
A void* typically isn't large enough to hold the data in a ponter-to-member. Even a "simple" pointer-to-member-data is more complicated than it looks, because the data might be in a virtual base, with no fixed offset in the derived type.
@digito_evo • there's std::declval to help out with not having an instance of the type — but it has some usage caveats (may make it not suitable for your particular use case in the original question).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.