Re: C++ nested classes, namespaces, structs, and compound statements

Daniel Berlin
2002-04-06T06:13:53Z

On Sat, 6 Apr 2002, Michael Elizabeth Chastain wrote:

> I'll bite.
>
> > In summary, the data structure GDB needs to represent C++ structs
> > (classes, unions, whatever) has a lot of similarities to the structure
> > GDB needs to represent the local variables of a compound statement.
>
> Sounds reasonable to me.
>
> It also sounds dangerous. It's true that namespaces, structs,
> and compound statements are all identifier binding contexts.
> But if you start treating a struct as a type of compound statement
> you could get into a maze of twisty forced meanings. You have to
> reach down and create a new paradigm and then port both structs
> and compound statements to it.
>
> Think about how much context information an identifier-binding-object
> needs to do its job. I think it would be difficult to come up with a
> universal context object that both structs and compound statements
> can use. Each identifier-binding-object has its own specialized
> context requirements.
>
> > - And what about ambiguous member names?
>
> The C++ language spec says: if class A inherits from both class B and
> class C, and both B and C have a member "foo_", then an unqualified
> reference to a.foo_ is illegal. The programmer has to say a::B.foo_
> or a::C.foo_.

Not quite.

Watch this cuteness, copied from the C++ draft standard:

struct U { static int i; };
struct V : U { };
struct W : U { using U::i; };
struct X : V, W { void foo(); };
void X::foo()
{
i; //Finds U::i in two ways: as W::i and U::i
// but no ambiguity because U::i is static

}

"A static member, a nested type or an enumerator defined in a base class T
can unambiguously be found even if an object has more than one base class
subobject of type T. Two base class subobjects share the non-static
member subobjects of their common virtual base classes"

In other words, it's not just statics.
Observe:

class V { public: int v; };
class A {
public:
int a;
static int s;
enum { e };
};
class B : public A, public virtual V {};
class C : public A, public virtual V {};
class D : public B, public C { };

void f(D* pd)
{
pd->v++; // ok: only one `v' (virtual)
pd->s++; // ok: only one `s' (static)
int i = pd->e; // ok: only one `e' (enumerator)
pd->a++; // error, ambiguous: two `a's in `D'
}