Reputation: 497
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
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
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
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
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