qualified member name lookup

V

vanyacpp

Hello,

If I compile the following program with gcc, clang or comeau I get a error about ambiguity. Is this correct behavior?

struct a
{
int foo;
};

struct a2 : virtual a
{};

struct b : a2
{};

struct c : a2
{};

struct d : b, c
{
void f()
{
b::a2::foo; // OK for MSVC, ERROR for others
}
};

(clang) error: ambiguous conversion from derived class 'd' to base class 'a2':
struct d -> struct b -> struct a2
struct d -> struct c -> struct a2

(gcc) error: 'a2' is an ambiguous base of 'd'

(comeau) error: base class "a2" is ambiguous

I explicitly specified that I want a2 in b. Why is there an ambiguity? I've looked in [basic.lookup.qual] and [class.member.lookup] and I haven't found anything relevant.

msvc doesn't show error about an ambiguity, but it also doesn't show errors in very simple cases (see below), so I don't take its results seriously.

struct a
{
int x;
};

struct b : a
{};

struct c : a
{};

struct x : b, c
{
void g()
{
a::x = 5; // OK for MSVC (and uses x->b->a), ERROR for others
}
};

Thanks in advance.
 
W

Werner

Hello,



If I compile the following program with gcc, clang or comeau
I get a error about ambiguity. Is this correct behavior?

IM(h)O, yes.

You inherited virtually from a, not a2. Therefore qualifying
through a is not ambigious. Two instances of a2 exist (as
you did not inherit virtually from it), which one (when
qualified)? Only one instance of a exists( as you inherited
virtually from it).

This works fine:

struct a
{
int foo;
};

struct a2 : virtual a
{};

struct b : a2
{};

struct c : a2
{};

struct d : b, c
{
void f()
{
a::foo;
}
};

Kind regards,

Werner
 
C

Casey Carter

struct a
{
int foo;
};

struct a2 : virtual a
{};

struct b : a2
{};

struct c : a2
{};

struct d : b, c
{
void f()
{
b::a2::foo; // OK for MSVC, ERROR for others
}
};

(clang) error: ambiguous conversion from derived class 'd' to base class 'a2':
struct d -> struct b -> struct a2
struct d -> struct c -> struct a2

(gcc) error: 'a2' is an ambiguous base of 'd'

(comeau) error: base class "a2" is ambiguous

Effectively, the compiler treats that expression as

static_cast<b::a2&>(*this).foo"

instead of

static_cast<a2&>(static_cast<b&>(*this)).foo

which you seem to expect.

The expression is class member access (5.2.5) equivalent to
(*this).b::a2::foo. According to the note in 5.2.5/2: "The program is
also ill-formed if the naming class is an ambiguous base of the class
type of the object expression; see 11.2." The naming class in this case
- a2 - is an ambiguous base of the object expression, *this with type d.
To be as clear as possible: the ambiguity doesn't occur in the name
lookup, but in the conversion of *this.

You can remove the ambiguous conversion of *this in this case by simply
referring to the member as "foo" or "a::foo" since a is a virtual base.
If a was NOT virtual, you could use the names "b::foo" and "c::foo"
since the conversions from d to b and d to c are unambiguous and the
name "foo" would still be unique in the scope of b and c.
 
I

Ivan Sorokin

Effectively, the compiler treats that expression as

   static_cast<b::a2&>(*this).foo"

instead of

   static_cast<a2&>(static_cast<b&>(*this)).foo

which you seem to expect.

To be as clear as possible: the ambiguity doesn't occur in the name
lookup, but in the conversion of *this.

This is what I inferred from experiment with clang.

Thank you very much.
 

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

Forum statistics

Threads
473,754
Messages
2,569,521
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top