Topic: Is this cast of pointer-to-member legal?
Author: paul.black@vf.vodafone.co.uk
Date: 1996/10/03 Raw View
Kevin Cline <kcline@i2.com> wrote:
> But what about the opposite case:
>
> struct B { };
> struct D : B { };
>
> struct C {
> typedef void (C::*action)( D& );
>
> void mb( B& ) { }
> void md( D& ) { }
> };
>
> void f( action ) { }
>
> It seems that
> f(&C::mb )
> should be a legal call, with no cast required. Is it?
It shouldn't be legal, it doesn't always work in the presence of multiple
inheritance. For example:
struct A { };
struct B { };
struct D : A, B { };
Paul
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Kevin Cline <kcline@i2.com>
Date: 1996/10/01 Raw View
"Marco Dalla Gasperina" <marcodg@hp-vcd.vcd.hp.com> writes:
>
> Paul J. Lucas <grumpy@wizard.arc.nasa.gov> wrote in article <pjl.843754146@wizard>...
> > Given:
> >
> > struct B { };
> > struct D : B { };
> >
> > struct C {
> > typedef void (C::*action)( B& );
> >
> > void mb( B& ) { }
> > void md( D& ) { }
> > };
> >
> > void f( action ) { }
> >
> > Is:
> >
> > f( (C::action)&C::md );
> >
> > a legal cast? The pointer-to-member is of the same class and 2
> > out of 3 C++ compilers agree that the cast is legal. Is the
> > 3rd one wrong?
>
> So, I think, it is legal. But not very smart...
>
> Consider a definition of f():
>
> void f( C::action mf )
> {
> C c;
> B b;
> c.*mf(b); // this will call C::md with a 'B' parameter. The
> // member probably assumes the extra capabilities of
> // a 'D' object but won't get them.
> }
>
> As usual, when one thinks they know more than the compiler, the compiler
> will exact a revenge.
>
But what about the opposite case:
struct B { };
struct D : B { };
struct C {
typedef void (C::*action)( D& );
void mb( B& ) { }
void md( D& ) { }
};
void f( action ) { }
It seems that
f(&C::mb )
should be a legal call, with no cast required. Is it?
--
Kevin Cline, i2 Technologies
--
Kevin Cline, i2 Technologies
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: Chelly Green <chelly@eden.com>
Date: 1996/10/02 Raw View
Kevin Cline wrote:
...
> But what about the opposite case:
>
> struct B { };
> struct D : B { };
>
> struct C {
> typedef void (C::*action)( D& );
>
> void mb( B& ) { }
> void md( D& ) { }
> };
>
> void f( action ) { }
>
> It seems that
>
> f(&C::mb )
>
> should be a legal call, with no cast required. Is it?
I guess this should be legal too?
typedef void (*action)( int, int );
void f( double, double );
void g( int, long );
void h( int, int, int = 0 );
action a = f;
action b = g;
action c = h;
Hey, the compiler could do type conversion and even provide default
arguments. But this requires hidden run-time functions, and possibly
complex rules. I think anything other than an exact match is going in
this direction. Pointer-to-members are just like other function pointers
in this regard.
I bet you could define a template function to do this (my compiler
doesn't support templates enough to do that, though... I tried!).
--
Chelly Green | chelly@eden.com | C++ - http://www.eden.com/~chelly
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Marco Dalla Gasperina" <marcodg@hp-vcd.vcd.hp.com>
Date: 1996/10/02 Raw View
Kevin Cline <kcline@i2.com> wrote in article
<l5hgoept2g.fsf@sc.i-have-a-misconfigured-system-so-shoot-me>...
>
> But what about the opposite case:
>
> struct B { };
> struct D : B { };
>
> struct C {
> typedef void (C::*action)( D& );
>
> void mb( B& ) { }
> void md( D& ) { }
> };
>
> void f( action ) { }
>
> It seems that
> f(&C::mb )
> should be a legal call, with no cast required. Is it?
Author: "Paul J. Lucas" <grumpy@wizard.arc.nasa.gov>
Date: 1996/09/26 Raw View
Given:
struct B { };
struct D : B { };
struct C {
typedef void (C::*action)( B& );
void mb( B& ) { }
void md( D& ) { }
};
void f( action ) { }
Is:
f( (C::action)&C::md );
a legal cast? The pointer-to-member is of the same class and 2
out of 3 C++ compilers agree that the cast is legal. Is the
3rd one wrong?
- Paul J. Lucas
NASA Ames Research Center Caelum Research Corporation
Moffett Field, California San Jose, California
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Marco Dalla Gasperina" <marcodg@hp-vcd.vcd.hp.com>
Date: 1996/09/27 Raw View
Paul J. Lucas <grumpy@wizard.arc.nasa.gov> wrote in article <pjl.843754146@wizard>...
> Given:
>
> struct B { };
> struct D : B { };
>
> struct C {
> typedef void (C::*action)( B& );
>
> void mb( B& ) { }
> void md( D& ) { }
> };
>
> void f( action ) { }
>
> Is:
>
> f( (C::action)&C::md );
>
> a legal cast? The pointer-to-member is of the same class and 2
> out of 3 C++ compilers agree that the cast is legal. Is the
> 3rd one wrong?
>From the April DWP:
| 5.4 Explicit type conversion (cast notation) [expr.cast]
|
|1 The result of the expression (T) cast-expression is of type T. An
| explicit type conversion can be expressed using functional notation
| (_expr.type.conv_), a type conversion operator (dynamic_cast,
| static_cast, reinterpret_cast, const_cast), or the cast notation.
| cast-expression:
| unary-expression
| ( type-id ) cast-expression
|
|2 Types shall not be defined in casts.
|
|3 Any type conversion not mentioned below and not explicitly defined by
| the user (_class.conv_) is ill-formed.
|
|4 The conversions performed by static_cast (_expr.static.cast_), rein
| terpret_cast (_expr.reinterpret.cast_), const_cast
| (_expr.const.cast_), or any sequence thereof, can be performed using
| the cast notation of explicit type conversion. The same semantic
| restrictions and behaviors apply. If a given conversion can be per
| formed using either static_cast or reinterpret_cast, the static_cast
To me, this says that if it can be done by reinterpret_cast<>() it is legal.
Again from the April DWP
| 5.2.9 Reinterpret cast [expr.reinterpret.cast]
|
|1 The result of the expression reinterpret_cast<T>(v) is the result of
| converting the expression v to type T. If T is a reference type, the
| result is an lvalue; otherwise, the result is an rvalue. Types shall
| not be defined in a reinterpret_cast. Conversions that can be per
| formed explicitly using reinterpret_cast are listed below. No other
| conversion can be performed explicitly using reinterpret_cast.
[2-9 elided]
|10An rvalue of type "pointer to member of X of type T1", can be explic
| itly converted to an rvalue of type "pointer to member of Y of type
| T2", if T1 and T2 are both function types or both data member types.
So, I think, it is legal. But not very smart...
Consider a definition of f():
void f( C::action mf )
{
C c;
B b;
c.*mf(b); // this will call C::md with a 'B' parameter. The
// member probably assumes the extra capabilities of
// a 'D' object but won't get them.
}
As usual, when one thinks they know more than the compiler, the compiler
will exact a revenge.
marco
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: paul.black@vf.vodafone.co.uk
Date: 1996/09/27 Raw View
Paul J. Lucas <grumpy@wizard.arc.nasa.gov> wrote:
> Given:
>
> struct B { };
> struct D : B { };
>
> struct C {
> typedef void (C::*action)( B& );
>
> void mb( B& ) { }
> void md( D& ) { }
> };
>
> void f( action ) { }
>
> Is:
>
> f( (C::action)&C::md );
>
> a legal cast? The pointer-to-member is of the same class and 2
> out of 3 C++ compilers agree that the cast is legal. Is the
> 3rd one wrong?
>
> - Paul J. Lucas
> NASA Ames Research Center Caelum Research Corporation
> Moffett Field, California San Jose, California
I'm not sure about legal, but the program is not working as you expect it it
does compile. Consider the following:
#include <iostream.h>
struct A { int a; };
struct B { int b; };
struct D : A, B { int d; };
struct C
{
typedef void (C::*action)( B& );
void mb( B& b) { cout << "B::b" << b.b << endl; }
void md( D& d)
{
cout << "D::b " << d.b << endl;
cout << "D::d " << d.d << endl;
}
};
void f( C::action a)
{
C c;
D d;
d.a = 1;
d.b = 2;
d.d = 3;
(c.*a)(d);
}
int main()
{
f( (C::action)&C::md );
return (0);
}
The output of the above program is (HP v3.72 C++, gcc 2.7.2):
D::b 3
D::d 0
At "(c.*a)(d)" the compiler believes that it has a "(C::*action)( B& )" and
adjusts the "d" that is passed (performing a "(B &)d"). This means that when
"void md( D& d)" is called, the "d" actually references a "B" not a "D"
Paul
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: Alexandre Oliva <oliva@dcc.unicamp.br>
Date: 1996/09/27 Raw View
>>>>> In article <pjl.843754146@wizard>, "Paul J. Lucas"
>>>>> <grumpy@wizard.arc.nasa.gov> writes:
> struct B { };
> struct D : B { };
> struct C {
> typedef void (C::*action)( B& );
> void md( D& ) { }
> };
> void f( C::action ) { }
> Is:
> f( (C::action)&C::md );
> a legal cast?
This cast is not a valid static_cast, so the compiler would use a
reinterpret_cast, that is, the resulting pointer-to-member might be
unusable --- the result is implementation defined. This means that:
// 1) conforming compilers should flag an error:
f( static_cast<C::action>(&C::md) );
// 2) implementation-defined results:
f( reinterpret_cast<C::action>(&C::md) );
// 3) equivalent to 2, since 1 is invalid
f( (C::action)(&C::md) );
--
Alexandre Oliva
mailto:oliva@dcc.unicamp.br
Universidade Estadual de Campinas, SP, Brasil
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]