Go Back   Rhinocerus > Newsgroup > Newsgroup comp.language.c++ > Newsgroup comp.language.c++.moderated

Reply
 
Thread Tools Display Modes
  #1 (permalink)  
Old 02-22-2012, 03:11 PM
Thomas Richter
Guest
 
Posts: n/a
Default Resolution of ambiguous members in multiple inheritance

If a class inheriting is a member of a same name from two distinct
bases, as in the following example:

struct A {
int a;

A()
: a(1)
{ }
};

struct B {
int a;

B()
: a(1)
{ }
};

struct C : public A,B {

int getA()
{
return a;
}
};

int main(int argc,char **argv)
{
struct C c;

return c.getA();
}

the compiler clearly refuses the code on the basis that C::a could be
either A::a or B::a. Somehow, I had the expectation that inserting a

struct C : public A,B {
using A::a; // <---
int getA()
{
return a;
}
};

should resolve this ambiguity, as it expresses what I would prefer to
do, but apparently, this is not the case. In this very harmless example,
replacing a by A::a in the getA() method would do, but in my real-life
example the number of required changes is a bit too large to make this a
convenient approach. The class layout found above (approximately) was
the outcome of a necessary refactoring of other code parts and the need
of the two (instead of one) base classes having access to the same
identical data.

My questions:

*) What is the rationale of not allowing the "using" directive to
resolve the ambiguity? It seems rather straight forward for me, but I
believe the compiler is correct here and it is a language design issue.
I would prefer to understand why the language does not make use of this
simple alternative.

*) Which other options do I have in this specific case? Note that in my
case I can even ensure that the values of the two "a" are constant and
identical throughout the life time of the classes, though I'm also happy
to discuss this issue in cases where this does not hold. virtual
inheritance where I move A::a into a common virtually derived base class
comes to my mind - any other options?

Thanks,
Thomas


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Reply With Quote
Alt Today
Advertising
 
and become member of Rhinocerus
Standard Sponsored Links

  #2 (permalink)  
Old 02-24-2012, 10:49 PM
Daniel Krügler
Guest
 
Posts: n/a
Default Re: Resolution of ambiguous members in multiple inheritance

On 2012-02-22 17:11, Thomas Richter wrote:
> If a class inheriting is a member of a same name from two distinct
> bases, as in the following example:
>
> struct A {
> int a;
>
> A()
> : a(1)
> { }
> };
>
> struct B {
> int a;
>
> B()
> : a(1)
> { }
> };
>
> struct C : public A,B {
>
> int getA()
> {
> return a;
> }
> };
>
> int main(int argc,char **argv)
> {
> struct C c;
>
> return c.getA();
> }
>
> the compiler clearly refuses the code on the basis that C::a could be
> either A::a or B::a. Somehow, I had the expectation that inserting a
>
> struct C : public A,B {
> using A::a; // <---
> int getA()
> {
> return a;
> }
> };
>
> should resolve this ambiguity, as it expresses what I would prefer to
> do, but apparently, this is not the case.


Adding the using-declaration should resolve the ambiguity. Which compiler did you test? (I'm not aware of any recent compiler that does not handle this situation properly).

HTH & Greetings from Bremen,

Daniel Krügler


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Reply With Quote
  #3 (permalink)  
Old 02-24-2012, 10:50 PM
Frank Birbacher
Guest
 
Posts: n/a
Default Re: Resolution of ambiguous members in multiple inheritance

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi!

Am 22.02.12 17:11, schrieb Thomas Richter:
> *) Which other options do I have in this specific case?


You could insert another class between C and A:

struct Intermediate : A
{
int getA() { return a; }
};

struct C : Intermediate, B
{
};

HTH,
Frank
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
Comment: GPGTools - http://gpgtools.org
Comment: keyserver x-hkp://pool.sks-keyservers.net

iEYEARECAAYFAk9F5DAACgkQhAOUmAZhnmrh/QCdEHNBA868jG9hEO1GKcdavFYv
Ln4An1fGaQJb1NtdEi0IjsPQzUbAxa82
=Kv98
-----END PGP SIGNATURE-----


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Reply With Quote
  #4 (permalink)  
Old 02-29-2012, 10:55 AM
Johannes Schaub
Guest
 
Posts: n/a
Default Re: Resolution of ambiguous members in multiple inheritance

Am 22.02.2012 17:11, schrieb Thomas Richter:
> If a class inheriting is a member of a same name from two distinct
> bases, as in the following example:
>
> struct A {
> int a;
>
> A()
> : a(1)
> { }
> };
>
> struct B {
> int a;
>
> B()
> : a(1)
> { }
> };
>
> struct C : public A,B {
>
> int getA()
> {
> return a;
> }
> };
>
> int main(int argc,char **argv)
> {
> struct C c;
>
> return c.getA();
> }
>
> the compiler clearly refuses the code on the basis that C::a could be
> either A::a or B::a. Somehow, I had the expectation that inserting a
>
> struct C : public A,B {
> using A::a; // <---
> int getA()
> {
> return a;
> }
> };
>
> should resolve this ambiguity, as it expresses what I would prefer to
> do, but apparently, this is not the case.


C++03 says that you first collect any declaration of any member name
called 'a' declared in any subobject (*subobject*, not class!). A
declaration in an object hides a declaration in all its base class
subobjects. It then says that a using-declaration "using X::y;" is
considered to be from each baseclass-subobjects of type "X".

The two interpretations of this originate from the time you adjust the
subobject-affinity of a using-declaration.

1) If you first do hiding and then do the adjustment (from C to C::A) in
your case, then you end up with a single declaraton found in subobject
C::A (found by your using-declaration which did hide both C::A::a and
C::B::a).

2) If you first do the adjustment (from C to C::A), and then do hiding,
you end up with three declarations found in two different subobjects
(C::A and C::B). This will be an error.

Only the first choice of interpretation will make your program be valid.
Possibly your compiler takes option "2)" and rejects your code for a
lookup ambiguity. In DR #39
(http://www.open-std.org/jtc1/sc22/wg...efects.html#39), the
committee applied option "1)" for deeming a different code invalid, but
they also say that the outcome of that route is undesired.

C++11 makes your code unambiguous unambiguously, however compilers need
to implement the C++11 rules first. Last time I checked, Clang and GCC
didn't do so yet.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Reply With Quote
  #5 (permalink)  
Old 03-02-2012, 09:33 AM
Thomas Richter
Guest
 
Posts: n/a
Default Re: Resolution of ambiguous members in multiple inheritance

Am 25.02.2012 00:49, schrieb Daniel Krügler:
> On 2012-02-22 17:11, Thomas Richter wrote:
>> If a class inheriting is a member of a same name from two distinct


> Adding the using-declaration should resolve the ambiguity. Which
> compiler did you test? (I'm not aware of any recent compiler that does
> not handle this situation properly).


That's gcc 4.4.5. Hmm. Thanks for noting, this seems to be a compiler
bug then. I'll try a later version.

So long,
Thomas


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

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off




All times are GMT. The time now is 06:23 AM.


Copyright ©2009

LinkBacks Enabled by vBSEO 3.3.0 RC2 © 2009, Crawlability, Inc.