C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Pointer to member, derived type not allowed?

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Boat
Guest





PostPosted: Tue Mar 15, 2005 3:57 pm    Post subject: Pointer to member, derived type not allowed? Reply with quote



The compiler complains that it can't convert a pointer to member of derived
type to a pointer to member of its base type. That is:

class B{};
class D : public B {}

class Foo
{
....
public:
D member;
};

B Foo::* pm = &Foo::member; // error, can't convert to B Foo::*

Two questions:
1) Why is this a problem?
2) How can I work around it? (I assume it's not an implemenation issue, but
haven't tried another compiler or platform. The "offender" is VC++ 7.)

A FAQ reference will be most humbly accepted. Live discussion will be better
for my mental well being.

Thanks.
Mike.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Victor Bazarov
Guest





PostPosted: Tue Mar 15, 2005 8:39 pm    Post subject: Re: Pointer to member, derived type not allowed? Reply with quote



Boat wrote:
Quote:
The compiler complains that it can't convert a pointer to member of derived
type to a pointer to member of its base type. That is:

class B{};
class D : public B {}

class Foo
{
...
public:
D member;
};

B Foo::* pm = &Foo::member; // error, can't convert to B Foo::*

Two questions:
1) Why is this a problem?

Because 'Foo' has no member of type 'B'. And such conversion does not
exist in the language.

Quote:
2) How can I work around it? (I assume it's not an implemenation issue, but
haven't tried another compiler or platform. The "offender" is VC++ 7.)

The "offender" is you. Any other compliant compiler will also complain.

Quote:
A FAQ reference will be most humbly accepted. Live discussion will be better
for my mental well being.

Why do you think you need such conversion? A couple of times we discussed
the possibility of allowing such conversion, but it seemed problematic to
the extend of not really giving a lot of advantage while requiring too
much trouble defining and implementing. Check out Google Groups, you will
probably find those discussions.

You probably can work around this by defining 'pm' to be a pointer to B
instead of a pointer to a member of Foo of type B:

B* pm = &somefoo.member; // 'somefoo' is an instance of 'Foo'.

V

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Pete Becker
Guest





PostPosted: Tue Mar 15, 2005 8:42 pm    Post subject: Re: Pointer to member, derived type not allowed? Reply with quote



Boat wrote:

Quote:
The compiler complains that it can't convert a pointer to member of derived
type to a pointer to member of its base type.

Members of derived classes are not necessarily members of base classes.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Dylan Nicholson
Guest





PostPosted: Tue Mar 15, 2005 9:02 pm    Post subject: Re: Pointer to member, derived type not allowed? Reply with quote

"Boat" <boat042-spam (AT) yahoo (DOT) com> wrote

Quote:
The compiler complains that it can't convert a pointer to member of derived
type to a pointer to member of its base type. That is:

class B{};
class D : public B {}

class Foo
{
...
public:
D member;
};

B Foo::* pm = &Foo::member; // error, can't convert to B Foo::*

Two questions:
1) Why is this a problem?
2) How can I work around it? (I assume it's not an implemenation issue, but
haven't tried another compiler or platform. The "offender" is VC++ 7.)

I assume you're trying to do something like this:


Foo* afoo = get_a_foo();

B& b = afoo->*pm;

b.some_virtual_function();


To be honest, I can't think of an in-principle reason why this would
not be possible or useful, but it certainly does seem to be forbidden
by the standard.
There are explicit rules about conversion of the type of the
*containing* class (in this case, 'foo'), but the return type must be
identical, as I understand it. Perhaps anything else would make
implementation messier than otherwise necessary.

As far as working around it - I guess you could use something like:

class B{};
class D : public B {};

class Foo
{
public:
Foo() : pmem(&member){ }
D member;
B* pmem;
};

B* Foo::* pm = &Foo::pmem;

(References don't seem to be allowed either - another
hard-to-understand restriction).

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Dylan Nicholson
Guest





PostPosted: Thu Mar 17, 2005 2:10 am    Post subject: Re: Pointer to member, derived type not allowed? Reply with quote

Pete Becker <petebecker (AT) acm (DOT) org> wrote

Quote:
Boat wrote:

The compiler complains that it can't convert a pointer to member of derived
type to a pointer to member of its base type.

Members of derived classes are not necessarily members of base classes.

Which has nothing to do with what the OP was asking (read it again!)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Boat
Guest





PostPosted: Thu Mar 17, 2005 2:14 am    Post subject: Re: Pointer to member, derived type not allowed? Reply with quote


"Victor Bazarov" <v.Abazarov (AT) comAcast (DOT) net> wrote

Quote:
Boat wrote:
The compiler complains that it can't convert a pointer to member of
derived
type to a pointer to member of its base type. That is:

class B{};
class D : public B {}

class Foo
{
...
public:
D member;
};

B Foo::* pm = &Foo::member; // error, can't convert to B Foo::*

Two questions:
1) Why is this a problem?

Because 'Foo' has no member of type 'B'. And such conversion does not
exist in the language.

D is a B by definition, and everywhere else convertable to a B. I understand
that the conversion of pointer to member is not in language. Why not was the
question. It doesn't seem particular error prone or (more) subject to
misuse.

Quote:
Why do you think you need such conversion? A couple of times we discussed
the possibility of allowing such conversion, but it seemed problematic to
the extend of not really giving a lot of advantage while requiring too
much trouble defining and implementing. Check out Google Groups, you will
probably find those discussions.

You probably can work around this by defining 'pm' to be a pointer to B
instead of a pointer to a member of Foo of type B:

B* pm = &somefoo.member; // 'somefoo' is an instance of 'Foo'.

The intended use was in yet-another database wrapper, mapping column names
to members.

class DbVariant
{
...
virtual bool Read(const char * col, DbStuff & rs) = 0;
};

class DbvLong : public DbVariant { .... }
class DbvString : public DbVariant { ... }

template <typename T>
struct DvName{
const char * fldName;
DbVariant T::* memb;
};

class ARowContainer
{
...
DbvLong aField;
DbvString anotherFld;
...
};

static const
DvName<ARowContainer> fooMap[] = {
{"a_column_name", &ARowContainer::aField},
{"another_column", &ARowContainer::anotherFld},
...
};

Iterating the list of DvName<> to populate the container would be trivially
simple, were this scheme possible. The problem is one of polymorphism, not
of pointer-ness. It would be possible to write DbVariant to respond to the
column data type in some other way, thereby simulating polymorphism. It
would be possible to treat every column as strings, perhaps, and suffer the
performance loss and possible mis-conversion. It remains possible to code
the read operations directly and manually. It would also be possible to
define each data member in the container using macros, to declare and define
a mutator which could then be called through a pointer to member function.
It can also be built as an indexed array, referenced by the data consumer
through an enumerator, or indirectly through accessors.

There are quite a few options, all of them less appealing than polymorphic
data members.

The problem is to succinctly define a mapping between a column name and a
data member that will contain its value. Both are known at compile time.
Polymorphism on data members seemed a reasonable solution.

I'll give it a day or so more, see if broader experience will write in and
enlighten. I'm leaning toward the associative list and accessors at the
moment as a workaround. The question remains, though, of why a pointer to
member should not be convertable to a pointer to member of its base type.
What possible harm or havoc can this produce?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Thu Mar 17, 2005 8:09 am    Post subject: Re: Pointer to member, derived type not allowed? Reply with quote

Pete Becker wrote:
Quote:
Boat wrote:

The compiler complains that it can't convert a pointer to
member of derived type to a pointer to member of its base
type.

Members of derived classes are not necessarily members of base
classes.

True, but §5.2.9 explicitly allows casting a D::* to a B::*.

And of course, this wasn't the original posters problem. In his
case, he was trying to convert a D Foo::* into a B Foo::*.
Logically, I can't think of any reason to forbid this, but the
standard doesn't seem to allow it.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Andrey Tarasevich
Guest





PostPosted: Thu Mar 17, 2005 12:30 pm    Post subject: Re: Pointer to member, derived type not allowed? Reply with quote

Boat wrote:
Quote:
The compiler complains that it can't convert a pointer to member of derived
type to a pointer to member of its base type. That is:

class B{};
class D : public B {}

class Foo
{
...
public:
D member;
};

B Foo::* pm = &Foo::member; // error, can't convert to B Foo::*

Two questions:
1) Why is this a problem?

It is just not allowed by the language specification. I don't think
there's any credible rationale behind this.

Quote:
2) How can I work around it? (I assume it's not an implemenation issue, but
haven't tried another compiler or platform. The "offender" is VC++ 7.)

One thing that comes to mind is to remove the covariant behavior from
this particular pointer by declaring it as a "pointer-to-member pointer"

B* Foo::* pm

and move that behavior to a regular pointer: an extra member of type
'B*' that has to be added to every object you need to work with

class Foo
{
...
B* pmember; // <- extra pointer
D member;
...
};

and initialize it in the class constructor as follows

Foo::Foo() : pmember(&member)
{ /* ... */ }

Now, instead of making 'pm' to point directly to 'Foo::member', you make
it to point to 'Foo::pmember'

B* Foo::* pm = &Foo::pmember;

This will introduce an extra level of indirection, i.e. in order to get
to the pointed object you'll have to use the dereference operator twice,
as in '*(obj.*pm)'. Note that in this case the covariant behavior is
actually implemented by a regular pointer, not by a member pointer.

This is, of course, rather convoluted non-elegant high-maintenance
solution. Very ugly. But formally it is "correct". Maybe someone will
come up with something more elegant.

P.S. It might turn out that if you actually introduce a 'pmember'
pointer as described above, there won't be any need for that 'pm'
pointer anymore, i.e. instead of '*(obj.*pm)' you'll be able to use a
simple '*obj.pmember'. Or maybe not. It depends on what you are trying
to implement, which I can't see from the code sample you provided.

--
Best regards,
Andrey Tarasevich

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Pete Becker
Guest





PostPosted: Thu Mar 17, 2005 9:41 pm    Post subject: Re: Pointer to member, derived type not allowed? Reply with quote

[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote:
Quote:

And of course, this wasn't the original posters problem. In his
case, he was trying to convert a D Foo::* into a B Foo::*.

Yup, I answered hastily. Thanks for your usual tactful correction.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.