Accessing hidden members of a class (as in x.A::B::y instead of x.y)

R

Rajib

If I have the following code

class B {
public: int b;
};

class C : public B {};

class E : public C, public B {};

int main() {
E x;
C y;
x.C::B::b++; //test3.cpp:14: error: ‘B’ is an ambiguous base of ‘E’
y.b++;
y.B::b++;
return 0;
}


Why is this ambiguous? I thought the compiler would look up C (and find
it unambiguously) and then use that to look up C::B (again finding it
unambiguously).

Thanks
 
D

Darío Griffo

If I have the following code

class B {
        public: int b;

};

class C : public B {};

class E : public C, public B {};

int main() {
        E x;
        C y;
        x.C::B::b++; //test3.cpp:14: error: ‘B’ is an ambiguous base of ‘E’
        y.b++;
        y.B::b++;
        return 0;

}

Because your don't need to inherit from C and B, only from C,
class E : public C, {};
x.B::b++;

If you do that, x is also a B
 
R

Rajib

Darío Griffo said:
Because your don't need to inherit from C and B, only from C,
class E : public C, {};
x.B::b++;

If you do that, x is also a B

Thanks for the response, but I'm not sure how that answers my question.
If I inherit from only C then looking up B as a member of C is
unambiguous; but if there are multiple instances (wrong word?) of B in
C, I'd expect to be able to specify them through their path of inheritance.

I'm more interested in how the compiler should resolve this than
actually writing such code.
 
J

James Kanze

If I have the following code
class B {
public: int b;
};
class C : public B {};
class E : public C, public B {};
int main() {
E x;
C y;
x.C::B::b++; //test3.cpp:14: error: ‘B’ is an ambiguous base of ‘E’
y.b++;
y.B::b++;
return 0;
}
Why is this ambiguous? I thought the compiler would look up C
(and find it unambiguously) and then use that to look up C::B
(again finding it unambiguously).

So did I, and my first reaction is to say that you'd encountered
a compiler error. In the expression x.C::B::b++, B and b should
be looked up using qualified name lookup, which finds the B in
C, and the b in B. VC++ accepts this, and I seem to recall
other compilers in the past accepting it as well (but it is a
very distant past, so I'm not really sure). G++ complains as
written (which I think is an error), but accepts x.C::b++. I
think that the consecrated solution here would be to cast this
to the target type: "static_cast< B* >( static_cast< C* >( &x )
)->b++" also works with g++.

Regardless, you don't want a hierarchy like this, since there is
no way to unambiguously refer to the B direct base of E (and
both g++ and VC++ warn about this).
 
R

Rajib

James said:
So did I, and my first reaction is to say that you'd encountered
a compiler error. In the expression x.C::B::b++, B and b should
be looked up using qualified name lookup, which finds the B in
C, and the b in B. VC++ accepts this, and I seem to recall
other compilers in the past accepting it as well (but it is a
very distant past, so I'm not really sure). G++ complains as
written (which I think is an error), but accepts x.C::b++. I
think that the consecrated solution here would be to cast this
to the target type: "static_cast< B* >( static_cast< C* >( &x )
)->b++" also works with g++.

Alright, so I guess the correct way to interpret
A x;
y.B::C::D::E::F::G::x;

is to make sure C is (unambiguously?) found in the class hierarchy of B,
D is (unambiguously?) found in the class hierarchy of C, etc... and then
throw all of that information away and just lookup G in A? The draft
standard says in 10.2 [class.member.lookup] that

"For an id-expression, name lookup begins in the class scope of this;
for a qualified-id, name lookup begins in the scope of the
nested-name-specifier."

Which seems to agree that g++/Comeau are correct (no surprise).

C++ makes less sense to me every day.

> Regardless, you don't want a hierarchy like this, since there is
> no way to unambiguously refer to the B direct base of E (and
> both g++ and VC++ warn about this).
>

Heh, I've never had to even use a qualified member lookup in actual
code; this is just test code for the program-resembling-a-compiler that
I'm writing.

Thanks all,
Rajib
 
J

James Kanze

* James Kanze:
No, it's probably correct; see my reply else-thread.
Comeau C/C++ 4.3.10.1 (May 29 2008 09:37:15) for ONLINE_EVALUATION_BETA1
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions
"ComeauTest.c", line 12: error: base class "B" is ambiguous
x.C::B::b++; //test3.cpp:14: error: ‘B’ is an ambiguous base of ‘E’
^
This seems to be correct.

Well, I won't argue about it. Mainly because I can't really
figure out what the standard is trying to say myself. And
because I don't consider it important, since such cases
shouldn't ever really occur in reasonable code. (Of course, if
you're writing a compiler, that's a different issue.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,818
Latest member
Brigette36

Latest Threads

Top