Davi
Davi

Reputation: 497

How do I print the address of a method pointer in C++?

For example:

struct A { void m() { } };

void stream_print() {
  void(A::*p)(void) = &A::m;
  std::cerr << p << std::endl;
}

void printf_print() {
  void(A::*p)(void) = &A::m;
  fprintf(stderr, "%p", p);
}

The stream_print() function always prints "1", which is obviously not what I want. The printf_print does not compile because p cannot be casted to void*.

What I need is a unique identifier for a method pointer that I can store in a container. I know this sounds like a bad idea, but I am developing a small toy for unit testing that can benefit from it. I am not worried about overloads of the method, I know how to get the pointer to a specific overload.

I am using g++ 4.4.3 with C++0x enabled.

Let me know if you have any doubts.

Upvotes: 7

Views: 1779

Answers (4)

mtvec
mtvec

Reputation: 18316

If it only needs to work with GCC, you could use this extension to extract a function pointer from a pointer to member function.

Here is an example:

#include <iostream>
#include <stdio.h>

struct A { void m() { } };

typedef void (*mptr)(A*);

int main()
{
    mptr p = (mptr)(&A::m);
    std::cerr << (void*)p << std::endl;
    fprintf(stderr, "%p\n", p);
}

Compile with -Wno-pmf-conversions to suppress the warning.

Upvotes: 1

Ise Wisteria
Ise Wisteria

Reputation: 11669

Though I'm not 100% sure I understand the question correctly, if some mapping from a member pointer to some unique id is needed, the following code might meet the purpose:

struct A {
  void f() {}
  void g( int ) {}
};

template< class T, T >
char* get_unique_id() {
  static char dummy;
  return &dummy;
}

int main() {
  set< char* >  s;
  s.insert( get_unique_id< decltype( &A::f ), &A::f >() );
  s.insert( get_unique_id< decltype( &A::g ), &A::g >() );
  s.insert( get_unique_id< decltype( &A::f ), &A::f >() );
  s.insert( get_unique_id< decltype( &A::g ), &A::g >() );
  cout<< s.size() <<endl; // prints 2
}

The call of get_unique_id is a little lengthy though...
Presumably some macro might help to make it simpler.

Hope this helps

Upvotes: 4

AnT stands with Russia
AnT stands with Russia

Reputation: 320531

Member function pointer is generally an object with non-trivial internal structure. Which is why you can't print it using tools intended for printing primitive types. Casting the pointer to void * is not a viable approach, since the size of member pointer is generally larger than sizeof(void *). Forcefully casting it to void * will in any case discard a portion of the pointer representation, thus no longer guaranteeing the uniqueness.

If what you are looking for is a unique string generated from the pointer, you can reinterpret the pointer as a character array, and use the string representation of character values in the identifier. Something like

void (A::*p)(void) = &A::m;

for (size_t i = 0; i < sizeof p; ++i)
  printf("%d ", reinterpret_cast<char *>(&p)[i]);

printf("\n");

Upvotes: 11

aschepler
aschepler

Reputation: 72356

There is no portable way to do this. But have you tried reinterpret_cast<void*>(p)?

I suspect stream_print is using std::operator<<(std::ostream&, bool), since that's the only valid conversion for a pointer-to-member type. That would explain why you get 1.

I wouldn't expect printf_print to work, even if a compiler did allow passing a pointer-to-member-function through .... There's no guarantee sizeof(p) == sizeof(void*), which is often a practical minimum for getting "expected" non-standard results from va_arg.

Upvotes: 0

Related Questions