Reading a method pointer from a stream

R

Rennie deGraaf

Let's say that I want to read a method pointer in from a stream. (I'm
not saying that this is a good design idea, or that I actually have a
reason to do this.) If I wanted to read in a function pointer, I could
do something like this:

#include <iostream>

int*(*readFunction())(int, int*)
{
unsigned long x;
std::cin >> x;
return reinterpret_cast<int*(*)(int, int*)>(x);
}

int main()
{
std::cout << reinterpret_cast<unsigned long>(readFunction()) <<
std::endl;
}

I'm assuming here that my input is valid and that an unsigned long is at
least as large as a pointer, but it works on my system.

However, if I try to do something similar to read in a pointer to a
method in a class A, like this:

#include <iostream>

struct A {
int* foo(int, int*)
{
return NULL;
}
};

int* (A::*readMethod())(int, int*)
{
unsigned long x;
std::cin >> x;
return reinterpret_cast<int*(A::*)(int, int*)>(x);
}

int main()
{
std::cout << reinterpret_cast<unsigned long>(readMethod()) <<
std::endl;
}

my compiler (g++ 4.0.2) spits out these errors:

test3.cpp: In function ‘int* (A::* readMethod())(int, int*)’:
test3.cpp:14: error: invalid cast from type ‘long unsigned int’ to
type ‘int* (A::*)(int, int*)’
test3.cpp: In function ‘int main()’:
test3.cpp:20: error: invalid cast from type ‘int* (A::*)(int, int*)’
to type ‘long unsigned int’

I can't simply change ReadMethod() to read in an int*(A::*)(int, int*)
without a cast, since there's no >> operator for that type, and I can't
think of a way to define one without a conversion from some integer type
at some point.

sizeof tells me that an int*(A::*)(int, int*) is 8 bytes on my system,
the same size as an unsigned long long (an g++ extension), but changing
"unsigned long" to "unsigned long long" in the above code doesn't change
the results.

Any suggestions on how to do this?

Thanks,
Rennie deGraaf
 
J

Jim Langston

Rennie deGraaf said:
Let's say that I want to read a method pointer in from a stream. (I'm
not saying that this is a good design idea, or that I actually have a
reason to do this.) If I wanted to read in a function pointer, I could
do something like this:

#include <iostream>

int*(*readFunction())(int, int*)
{
unsigned long x;
std::cin >> x;
return reinterpret_cast<int*(*)(int, int*)>(x);
}

int main()
{
std::cout << reinterpret_cast<unsigned long>(readFunction()) <<
std::endl;
}

I'm assuming here that my input is valid and that an unsigned long is at
least as large as a pointer, but it works on my system.

However, if I try to do something similar to read in a pointer to a
method in a class A, like this:

#include <iostream>

struct A {
int* foo(int, int*)
{
return NULL;
}
};

int* (A::*readMethod())(int, int*)
{
unsigned long x;
std::cin >> x;
return reinterpret_cast<int*(A::*)(int, int*)>(x);
}

int main()
{
std::cout << reinterpret_cast<unsigned long>(readMethod()) <<
std::endl;
}

my compiler (g++ 4.0.2) spits out these errors:

test3.cpp: In function ‘int* (A::* readMethod())(int, int*)’:
test3.cpp:14: error: invalid cast from type ‘long unsigned int’ to
type ‘int* (A::*)(int, int*)’
test3.cpp: In function ‘int main()’:
test3.cpp:20: error: invalid cast from type ‘int* (A::*)(int, int*)’
to type ‘long unsigned int’

I can't simply change ReadMethod() to read in an int*(A::*)(int, int*)
without a cast, since there's no >> operator for that type, and I can't
think of a way to define one without a conversion from some integer type
at some point.

sizeof tells me that an int*(A::*)(int, int*) is 8 bytes on my system,
the same size as an unsigned long long (an g++ extension), but changing
"unsigned long" to "unsigned long long" in the above code doesn't change
the results.

Any suggestions on how to do this?

Thanks,
Rennie deGraaf

Consider a union. A union is usually a cheap way to do a conversion that C
or C++ doesn't want to do. You'll have to play around with the proper sytax
to get the function pointer to work, but I'll presume that your function
pointer is working correctly.

union
{
int* (A::*readMethod())(int, int*);
unsigned unsigned long Pointer;
} ConvertPoint;

std::cin >> ConvertPoint.Pointer;

at this point readMethod would contain the pointer.

Of course none of this is really safe or in any conceivable way portable.
It should work the other way to, assign readPointer and the Pointer var
holds the int ... umm.. version? of it.
 
R

Rennie deGraaf

Jim said:
Consider a union. A union is usually a cheap way to do a conversion that C
or C++ doesn't want to do. You'll have to play around with the proper sytax
to get the function pointer to work, but I'll presume that your function
pointer is working correctly.

union
{
int* (A::*readMethod())(int, int*);
unsigned unsigned long Pointer;
} ConvertPoint;

std::cin >> ConvertPoint.Pointer;

at this point readMethod would contain the pointer.

Of course none of this is really safe or in any conceivable way portable.
It should work the other way to, assign readPointer and the Pointer var
holds the int ... umm.. version? of it.

Thanks, that's a good idea.

I was messing around with a framework that I wrote that can serialize
and deserialize objects of any type, trying to see how many types of
types I could handle with it. I can make it work for POD types,
classes, template classes, data pointers, function pointers, and now,
method pointers. It won't work with arrays or references. Am I missing
anything?

Rennie deGraaf
 
J

Jim Langston

Rennie deGraaf said:
Thanks, that's a good idea.

I was messing around with a framework that I wrote that can serialize
and deserialize objects of any type, trying to see how many types of
types I could handle with it. I can make it work for POD types,
classes, template classes, data pointers, function pointers, and now,
method pointers. It won't work with arrays or references. Am I missing
anything?

Rennie deGraaf

bool and bitfields? // should be fairly easy

enums? // should be fairly easy

How about std::string? That might prove intesting since the actual data is
not stored in the string object itself but memory the object points to. I
think you'd have that problem with all stl containers, but std::string is
definately necessary. You might as well do vector to as they'll be close to
identical. Although populating them would probably be different.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top