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 

Re: Using declarations and class member ambiguities

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language, library and standards
View previous topic :: View next topic  
Author Message
William M. Miller
Guest





PostPosted: Wed Jul 09, 2003 10:03 pm    Post subject: Re: Using declarations and class member ambiguities Reply with quote



""William Hayes"" <whayes (AT) hfx (DOT) andara.com> wrote

Quote:
The Standard says that "...because a using-declaration designates a base
class member (and not a member subobject or a member function of a base
class subobject), a using-declaration cannot be used to resolve inherited
member ambiguities" (7.3.3, 14). The example it cites involves an
inheritance hierarchy containing multiple copies of a base class:

struct A { int x(); };
struct B : A { };
struct C: A {
using A:Mad;
int x(int);
};
struct D : B, C {
using C:Mad;
int x(double);
};

int f(D* d) {
return d->x(); // ambiguous: B:Mad or C:Mad
}

My first question is, Why can't the using declaration be used to perform
this kind of disambiguation? If the using declaration declares function x
in struct D as a "synonym" for C:Mad, it seems that it would be reasonable
to
expect that d->x() would call C:Mad, just as d->C:Mad() would.

The only effect of a using-declaration (apart from overload
resolution) is to prevent hiding of base class names by
derived class declarations. It doesn't do anything else.
In particular, the two using-declarations in the example
above just mean that A:Mad() is not hidden by the declarations
in C and D. However, there are two subobjects of type A, so
the lookup set has two A:Mad() members. (See 10.2p2: "Each of
these declarations that was introduced by a using-declaration
is considered to be from each sub-object of C that is of the
type containing the declaration designated by the
using-declaration.")

Another way of looking at this is that using-declarations
deal only with types, not objects (cf "each sub-object ...
of the _type_ containing the declaration..." in the preceding
citation [emphasis added]).

Quote:
In spite of the Standard's general refusal to allow the using declaration
to
resolve inherited member ambiguities, several compilers (Comeau 4.3.0.1,
g++
3.2, Borland 5.5.1) allow the following:

#include
class X { public: char x(){ return 'X';} };
class Y { public: char x(){ return 'Y';} };
class Z : public X, public Y {
public:
using X:Mad;
};

int main() {
Z z;
assert( z.x() == 'X' );
}

My second question is, Does the Standard allow this behavior?

Yes. The using-declaration hides Y:Mad(), and there's only one
subobject of type X in Z, so there's no ambiguity.

-- William M. Miller


---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]


Back to top
William Hayes
Guest





PostPosted: Thu Jul 10, 2003 5:42 pm    Post subject: Re: Using declarations and class member ambiguities Reply with quote




"Daveed Vandevoorde" <google (AT) vandevoorde (DOT) com> wrote

Quote:
whayes (AT) hfx (DOT) andara.com ("William Hayes") wrote:
The Standard says that "...because a using-declaration designates a base
class member (and not a member subobject or a member function of a base
class subobject), a using-declaration cannot be used to resolve
inherited
member ambiguities" (7.3.3, 14). The example it cites involves an
inheritance hierarchy containing multiple copies of a base class:

struct A { int x(); };
struct B : A { };
struct C: A {
using A:Mad;
int x(int);
};
struct D : B, C {
using C:Mad;
int x(double);
};

int f(D* d) {
return d->x(); // ambiguous: B:Mad or C:Mad
}

My first question is, Why can't the using declaration be used to perform
this kind of disambiguation? If the using declaration declares function
x
in struct D as a "synonym" for C:Mad, it seems that it would be
reasonable to
expect that d->x() would call C:Mad, just as d->C:Mad() would.

A using declaration is a mechanism to direct lookup. To process the
expression "d->x()" a compiler has to do several things, among which:
(a) look up x.
(b) perform overload resolution if there are multiple x.
(c) convert d to the appropriate type to serve as a "this"
pointer for the selected x.

Using declarations only affect (a); not (c) (or (b), obviously).

In you example, the using declarations cause the overload set (i.e.,
the result of looking up x) to consist of:
A:Mad()
B:Mad(int)
C:Mad(double)
Overload resolution easily picks A:Mad(), which means that d must
be converted to an A*, and it is that part that is ambiguous.

In spite of the Standard's general refusal to allow the using
declaration to
resolve inherited member ambiguities, several compilers (Comeau 4.3.0.1,
g++
3.2, Borland 5.5.1) allow the following:

#include
class X { public: char x(){ return 'X';} };
class Y { public: char x(){ return 'Y';} };
class Z : public X, public Y {
public:
using X:Mad;
};

int main() {
Z z;
assert( z.x() == 'X' );
}

My second question is, Does the Standard allow this behavior?

Sure, applying the principles above, the overload set is a singleton:
X:Mad()
Overload resolution is trivial, and the conversion of the Z& to X& is
unambiguous.

So, class member lookup returns (in effect) a list of qualified class member
names. Each name on the list specifies a class that actually contains a
declaration of that member (e.g., A:Mad), never a derived class that merely
inherited one (e.g., C:Mad). Is that correct?

Does the prohibition against using the using declaration for this kind of
disambiguation therefore reflect the way name lookup works, rather than a
design decision related to the using declaration itself?

Thanks.
__________________________
William Hayes
Raven Software Limited

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]


Back to top
William Hayes
Guest





PostPosted: Fri Jul 11, 2003 1:39 am    Post subject: Re: Using declarations and class member ambiguities Reply with quote




""William M. Miller"" <wmm (AT) world (DOT) std.com> wrote

Quote:
""William Hayes"" <whayes (AT) hfx (DOT) andara.com> wrote in message
news:jFXMa.33361$PD3.111394 (AT) nnrp1 (DOT) uunet.ca...
The Standard says that "...because a using-declaration designates a base
class member (and not a member subobject or a member function of a base
class subobject), a using-declaration cannot be used to resolve
inherited
member ambiguities" (7.3.3, 14). The example it cites involves an
inheritance hierarchy containing multiple copies of a base class:

struct A { int x(); };
struct B : A { };
struct C: A {
using A:Mad;
int x(int);
};
struct D : B, C {
using C:Mad;
int x(double);
};

int f(D* d) {
return d->x(); // ambiguous: B:Mad or C:Mad
}

My first question is, Why can't the using declaration be used to perform
this kind of disambiguation? If the using declaration declares function
x
in struct D as a "synonym" for C:Mad, it seems that it would be
reasonable
to
expect that d->x() would call C:Mad, just as d->C:Mad() would.

The only effect of a using-declaration (apart from overload
resolution) is to prevent hiding of base class names by
derived class declarations. It doesn't do anything else.
In particular, the two using-declarations in the example
above just mean that A:Mad() is not hidden by the declarations
in C and D. However, there are two subobjects of type A, so
the lookup set has two A:Mad() members. (See 10.2p2: "Each of
these declarations that was introduced by a using-declaration
is considered to be from each sub-object of C that is of the
type containing the declaration designated by the
using-declaration.")

Another way of looking at this is that using-declarations
deal only with types, not objects (cf "each sub-object ...
of the _type_ containing the declaration..." in the preceding
citation [emphasis added]).

In spite of the Standard's general refusal to allow the using
declaration
to
resolve inherited member ambiguities, several compilers (Comeau 4.3.0.1,
g++
3.2, Borland 5.5.1) allow the following:

#include
class X { public: char x(){ return 'X';} };
class Y { public: char x(){ return 'Y';} };
class Z : public X, public Y {
public:
using X:Mad;
};

int main() {
Z z;
assert( z.x() == 'X' );
}

My second question is, Does the Standard allow this behavior?

Yes. The using-declaration hides Y:Mad(), and there's only one
subobject of type X in Z, so there's no ambiguity.

Do all of the effects of the using declaration on member lookup boil down to
effects on name hiding? In the first example, the using declarations pull
C:Mad(int) and A:Mad() into the scope of D (in a sense), preventing
D:Mad(double) from hiding them. In the second, the using declaration pulls
X:Mad into the scope of Z, causing X:Mad to hide Y:Mad instead of conflicting
with it.

When you mention the effect of using declarations on overload resolution,
are you referring to its indirect effect, through its influence on the
composition of the lookup set?

Thanks.
__________________________
William Hayes
Raven Software Limited

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]


Back to top
William M. Miller
Guest





PostPosted: Sat Jul 12, 2003 12:15 am    Post subject: Re: Using declarations and class member ambiguities Reply with quote

""William Hayes"" <whayes (AT) hfx (DOT) andara.com> wrote


Quote:
Do all of the effects of the using declaration on member lookup boil down
to
effects on name hiding? In the first example, the using declarations pull
C:Mad(int) and A:Mad() into the scope of D (in a sense), preventing
D:Mad(double) from hiding them. In the second, the using declaration pulls
X:Mad into the scope of Z, causing X:Mad to hide Y:Mad instead of conflicting
with it.

Yes. Of course, there are also effects on access and overloading,
but in terms of name lookup, it's just for circumventing hiding.
(It's different with namespace using-declarations, where visibility
is the principal effect, but since base class members are visible
in derived classes unless hidden, for member using-declarations it's
all about avoiding hiding.)

Quote:
When you mention the effect of using declarations on overload resolution,
are you referring to its indirect effect, through its influence on the
composition of the lookup set?

No, I was thinking of 7.3.3p13 -- the implicit "this" parameter of
a non-static member function is assumed to be the type of the class
in which the using-declaration appears, not that of the class of
which it is directly a member. Here's an example where that makes
a difference:

struct B {
void f(char);
};
struct D: B {
using B::f;
void f(int);
};
void x(D* dp) {
dp->f('c');
}

If it weren't for this rule, the call "dp->f('c')" would be
ambiguous -- the 'c' is a better match for B::f(char), but "dp" would
be a better match for D::f(int). Because of the using-declaration,
B::f(char) is treated for overload resolution as if its "this" were
a D* instead of a B*, allowing the two member functions to compete
solely on the basis of their explicit parameter types.

-- William M. Miller


---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language, library and standards 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.