Topic: Funtion pointer casts


Author: "Philippe A. Bouchard" <philippeb@corel.com>
Date: Fri, 9 Mar 2001 21:59:41 GMT
Raw View
Is there any reason why the following cast is not working:
struct Object
{
};

struct Derived : public Object
{
};

int main()
{
    void (* p1)(Derived *);
    void (* p2)(Object *) = p1;
}

fpointercast.cpp: In function `int main()':
fpointercast.cpp:12: initialization to `void (*)(Object *)' from `void
(*)(Derived *)'

Thanks.

--
Philippe A. Bouchard
Corel Linux



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: gt5163b@prism.gatech.edu (Brian McNamara!)
Date: Fri, 9 Mar 2001 23:57:07 GMT
Raw View
"Philippe A. Bouchard" <philippeb@corel.com> once said:
>Is there any reason why the following cast is not working:
>struct Object
>{
>};
>
>struct Derived : public Object
>{
>};
>
>int main()
>{
>    void (* p1)(Derived *);
>    void (* p2)(Object *) = p1;
>}
>
>fpointercast.cpp: In function `int main()':
>fpointercast.cpp:12: initialization to `void (*)(Object *)' from `void
>(*)(Derived *)'

I think there are two reasons it doesn't work.  First, you're trying to
assign the wrong way; LSP suggests that p2 is a subtype of p1 (functions
vary contravariantly in their arguments), so you could assign
   p1 = p2
but the other assignment (p2=p1) would need a dynamic_cast of sorts.

Second, the C++ type system doesn't work this way with function pointers
anyway; as far as C++ is concerned, the types of p1 and p2 are
unrelated, even if we know that they should be "in theory".


As a practical matter, if you do want a subtyping relationship among
"function pointers", you can check out the "indirect functoids" in the
FC++ library:

   http://www.cc.gatech.edu/~yannis/fc++/

Specifically, the examples at

   http://www.cc.gatech.edu/~yannis/fc++/FC++-clients.1.2.1/conv_fun.cc

are suggestive.  In you case, you can say

   #include "prelude.h"

   #include <iostream>
   using std::cout;
   using std::endl;

   struct Object {};
   struct Derived : public Object {};

   void f( Object* ) { cout << "hi" << endl; }

   int main() {
      Fun1<Object*,void>  o = &f;  // Fun1<A,B> is like B(*)(A), only better
      Fun1<Derived*,void> d = o;   // because you can do this
      d( new Derived );
   }

which compiles and works as expected.

--
 Brian M. McNamara   lorgon@acm.org  :  I am a parsing fool!
   ** Reduce - Reuse - Recycle **    :  (Where's my medication? ;) )

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Ron Natalie <ron@spamcop.net>
Date: Sat, 10 Mar 2001 13:17:33 GMT
Raw View

"Philippe A. Bouchard" wrote:
>
> Is there any reason why the following cast is not working:

What cast?  I see no cast.

>     void (* p1)(Derived *);
>     void (* p2)(Object *) = p1;
> }
>
> fpointercast.cpp: In function `int main()':
> fpointercast.cpp:12: initialization to `void (*)(Object *)' from `void
> (*)(Derived *)'
>

The ONLY implicit conversion on pointer-to-member is that you can convert
A pointer to member of T Base::* to T Derived::*.  The type of the pointed
to member must be the same.  You can not convert T1 Base::* to T2 Base::*
even if there is an defined conversion from T1 to T2.  And there isn't even
such a converion (no such thing as covariant function arguments, only function
return values).

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: "Gary Mussar" <mussar@nortelnetworks.com>
Date: Mon, 12 Mar 2001 19:17:30 GMT
Raw View
"Ron Natalie" <ron@spamcop.net> wrote in message
news:3AA95762.F43ECB7D@spamcop.net...
> "Philippe A. Bouchard" wrote:
> >     void (* p1)(Derived *);
> >     void (* p2)(Object *) = p1;
> The ONLY implicit conversion on pointer-to-member is that you can convert
> A pointer to member of T Base::* to T Derived::*.  The type of the pointed
> to member must be the same.  You can not convert T1 Base::* to T2 Base::*
> even if there is an defined conversion from T1 to T2.  And there isn't
even
> such a converion (no such thing as covariant function arguments, only
function
> return values).

But these are not PMFs, these are simple function pointers.

The type system treats these as completely separate types even though many
designers assume that they should be related. If you were dealing directly
with the functions, the compiler would know the signature of the functions,
the types of the passed parameter and could convert derived class pointers
to base class pointers when necessary. The same is not possible with a
function pointer that may possibly be initialized to either a function that
takes a base pointer or to a function that takes a derived pointer.

To many designers assume that the conversion of a derived pointer to a base
pointer is a no-op. This is not true. It may involve adjustments to the
instance pointer to point to the actual location of the base object inside
the derived object. Think of the case of multiple inheritance. Only one of
the base classes could possibly be located exactly at the beginning of the
derived object.

Gary


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]