Reading a method pointer from a stream

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Rennie deGraaf

    #1

    Reading a method pointer from a stream

    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*(*readFunct ion())(int, int*)
    {
    unsigned long x;
    std::cin >> x;
    return reinterpret_cas t<int*(*)(int, int*)>(x);
    }

    int main()
    {
    std::cout << reinterpret_cas t<unsigned long>(readFunct ion()) <<
    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_cas t<int*(A::*)(in t, int*)>(x);
    }

    int main()
    {
    std::cout << reinterpret_cas t<unsigned long>(readMetho d()) <<
    std::endl;
    }

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

    test3.cpp: In function ‘int* (A::* readMethod())(i nt, 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
  • Jim Langston

    #2
    Re: Reading a method pointer from a stream

    "Rennie deGraaf" <ca.ucalgary.cp sc@degraaf> wrote in message
    news:_Gnxf.8620 8$tl.63562@pd7t w3no...[color=blue]
    > 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*(*readFunct ion())(int, int*)
    > {
    > unsigned long x;
    > std::cin >> x;
    > return reinterpret_cas t<int*(*)(int, int*)>(x);
    > }
    >
    > int main()
    > {
    > std::cout << reinterpret_cas t<unsigned long>(readFunct ion()) <<
    > 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_cas t<int*(A::*)(in t, int*)>(x);
    > }
    >
    > int main()
    > {
    > std::cout << reinterpret_cas t<unsigned long>(readMetho d()) <<
    > std::endl;
    > }
    >
    > my compiler (g++ 4.0.2) spits out these errors:
    >
    > test3.cpp: In function ‘int* (A::* readMethod())(i nt, 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[/color]

    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.Po inter;

    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.


    Comment

    • Rennie deGraaf

      #3
      Re: Reading a method pointer from a stream

      Jim Langston wrote:[color=blue]
      > "Rennie deGraaf" <ca.ucalgary.cp sc@degraaf> wrote in message
      > news:_Gnxf.8620 8$tl.63562@pd7t w3no...
      >[color=green]
      >>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*(*readFunct ion())(int, int*)
      >> {
      >> unsigned long x;
      >> std::cin >> x;
      >> return reinterpret_cas t<int*(*)(int, int*)>(x);
      >> }
      >>
      >> int main()
      >> {
      >> std::cout << reinterpret_cas t<unsigned long>(readFunct ion()) <<
      >>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_cas t<int*(A::*)(in t, int*)>(x);
      >> }
      >>
      >> int main()
      >> {
      >> std::cout << reinterpret_cas t<unsigned long>(readMetho d()) <<
      >>std::endl;
      >> }
      >>
      >>my compiler (g++ 4.0.2) spits out these errors:
      >>
      >> test3.cpp: In function ‘int* (A::* readMethod())(i nt, 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[/color]
      >
      >
      > 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.Po inter;
      >
      > 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.[/color]

      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

      Comment

      • Jim Langston

        #4
        Re: Reading a method pointer from a stream


        "Rennie deGraaf" <ca.ucalgary.cp sc@degraaf> wrote in message
        news:xexxf.2017 37$2k.196441@pd 7tw1no...[color=blue]
        > Jim Langston wrote:[color=green]
        >> "Rennie deGraaf" <ca.ucalgary.cp sc@degraaf> wrote in message
        >> news:_Gnxf.8620 8$tl.63562@pd7t w3no...
        >>[color=darkred]
        >>>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*(*readFunct ion())(int, int*)
        >>> {
        >>> unsigned long x;
        >>> std::cin >> x;
        >>> return reinterpret_cas t<int*(*)(int, int*)>(x);
        >>> }
        >>>
        >>> int main()
        >>> {
        >>> std::cout << reinterpret_cas t<unsigned long>(readFunct ion()) <<
        >>>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_cas t<int*(A::*)(in t, int*)>(x);
        >>> }
        >>>
        >>> int main()
        >>> {
        >>> std::cout << reinterpret_cas t<unsigned long>(readMetho d()) <<
        >>>std::endl;
        >>> }
        >>>
        >>>my compiler (g++ 4.0.2) spits out these errors:
        >>>
        >>> test3.cpp: In function ‘int* (A::* readMethod())(i nt, 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[/color]
        >>
        >>
        >> 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.Po inter;
        >>
        >> 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.[/color]
        >
        > 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[/color]

        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.



        Comment

        Working...