Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > strange ambiguity in the derived class

Reply
Thread Tools

strange ambiguity in the derived class

 
 
vj
Guest
Posts: n/a
 
      05-11-2010
Hello,

Trying to compile the example at the end of this post, I am getting
next errors:

[packman@localhost test]$ g++ p.cpp
p.cpp: In member function ‘void D::foo1()’:
p.cpp:39: error: request for member ‘boo’ is ambiguous
p.cpp:16: error: candidates are: const int& B::boo() const
p.cpp:6: error: int& A::boo()
p.cpp: In member function ‘void D::foo2() const’:
p.cpp:41: error: request for member ‘boo’ is ambiguous
p.cpp:16: error: candidates are: const int& B::boo() const
p.cpp:6: error: int& A::boo()


Can someone explain why the example doesn't compile?
The signatures of A:boo() and B:boo() methods are different (one is
const, other isn't).

How to change the example, to make it compile?

Thank in advance.




And the example is here:

#include <iostream>
class A
{
public:
virtual ~A(){}
int& boo()
{ return vboo(); }
private:
virtual int& vboo() = 0;
};

class B
{
public:
virtual ~B(){}
const int& boo() const
{ return vboo(); }
private:
virtual const int& vboo() const = 0;
};

class C : public A, public B
{
public:
C()(5){}
virtual ~C(){}
private:
virtual const int& vboo() const
{ return p; }
virtual int& vboo()
{ return p; }
int p;
};

class D
{
public:
void foo1()
{ std::cout<<"D::foo1() ++c.boo()="<<++c.boo()<<std::endl; }
void foo2() const
{ std::cout<<"D::foo1() c.boo()const="<<c.boo()<<std::endl; }
private:
C c;
};

int main()
{
D d;
d.foo1();
d.foo2();
}

 
Reply With Quote
 
 
 
 
Alf P. Steinbach
Guest
Posts: n/a
 
      05-11-2010
On 11.05.2010 08:23, * vj:
> Hello,
>
> Trying to compile the example at the end of this post, I am getting
> next errors:
>
> [packman@localhost test]$ g++ p.cpp
> p.cpp: In member function ‘void D::foo1()’:
> p.cpp:39: error: request for member ‘boo’ is ambiguous
> p.cpp:16: error: candidates are: const int& B::boo() const
> p.cpp:6: error: int& A::boo()
> p.cpp: In member function ‘void D::foo2() const’:
> p.cpp:41: error: request for member ‘boo’ is ambiguous
> p.cpp:16: error: candidates are: const int& B::boo() const
> p.cpp:6: error: int& A::boo()
>
>
> Can someone explain why the example doesn't compile?
> The signatures of A:boo() and B:boo() methods are different (one is
> const, other isn't).
>
> How to change the example, to make it compile?
>
> Thank in advance.
>
>
>
>
> And the example is here:
>
> #include<iostream>
> class A
> {
> public:
> virtual ~A(){}
> int& boo()
> { return vboo(); }
> private:
> virtual int& vboo() = 0;
> };
>
> class B
> {
> public:
> virtual ~B(){}
> const int& boo() const
> { return vboo(); }
> private:
> virtual const int& vboo() const = 0;
> };
>
> class C : public A, public B
> {
> public:
> C()(5){}
> virtual ~C(){}
> private:
> virtual const int& vboo() const
> { return p; }
> virtual int& vboo()
> { return p; }
> int p;
> };
>
> class D
> {
> public:
> void foo1()
> { std::cout<<"D::foo1() ++c.boo()="<<++c.boo()<<std::endl; }
> void foo2() const
> { std::cout<<"D::foo1() c.boo()const="<<c.boo()<<std::endl; }
> private:
> C c;
> };
>
> int main()
> {
> D d;
> d.foo1();
> d.foo2();
> }


The error is apparently caused by the possible boo's coming from different
classes, at some point before their signatures are considered.

I think you can find the relevant sections of the standard yourself, but as a
practical matter, put

using A::boo;
using B::boo;

in the public section of your C class.

Then (apparently) the compiler is happy to also consider the signatures, and
discovers that one of them is a better match.


Cheers & hth.,

- Alf
(blog at <url: http://alfps.wordpress.com>)
 
Reply With Quote
 
 
 
 
Öö Tiib
Guest
Posts: n/a
 
      05-11-2010
On May 11, 9:23*am, vj <(E-Mail Removed)> wrote:
> Hello,
>
> Trying to compile the example at the end of this post, I am getting
> next errors:
>
> [packman@localhost test]$ g++ p.cpp
> p.cpp: In member function ‘void D::foo1()’:
> p.cpp:39: error: request for member ‘boo’ is ambiguous
> p.cpp:16: error: candidates are: const int& B::boo() const
> p.cpp:6: error: * * * * * * * * int& A::boo()
> p.cpp: In member function ‘void D::foo2() const’:
> p.cpp:41: error: request for member ‘boo’ is ambiguous
> p.cpp:16: error: candidates are: const int& B::boo() const
> p.cpp:6: error: * * * * * * * * int& A::boo()
>
> Can someone explain why the example doesn't compile?


Because compiler does not understand what it is that you are
attempting to call. Also it (in better English than i usually use)
explains it in its error messages.

> The signatures of A:boo() and B:boo() methods are different (one is
> const, other isn't).


So what? Your compiler anyway failed to resolve between them. Also
newbie reading your code will likely be confused.

> How to change the example, to make it compile?


Either rename one of the functions from ambiquous candidate set
(compiler very nicely explains what these are) or make it explicit
what it is that you are calling by qualifying the called function.

> Thank in advance.


You are welcome.

> And the example is here:
>
> #include <iostream>
> class A
> {
> * public:
> * * virtual ~A(){}
> * * int& boo()
> * * { return vboo(); }
> * private:
> * * virtual int& vboo() = 0;
>
> };
>
> class B
> {
> * public:
> * * virtual ~B(){}
> * * const int& boo() const
> * * { return vboo(); }
> * private:
> * * virtual const int& vboo() const = 0;
>
> };
>
> class C : public A, public B
> {
> * public:
> * * C()(5){}
> * * virtual ~C(){}
> * private:
> * * virtual const int& vboo() const
> * * { return p; }
> * * virtual int& vboo()
> * * { return p; }
> * * int p;
>
> };
>
> class D
> {
> * public:
> * * void foo1()
> * * { std::cout<<"D::foo1() * ++c.boo()="<<++c.boo()<<std::endl; }
> * * void foo2() const
> * * { std::cout<<"D::foo1() * c.boo()const="<<c.boo()<<std::endl; }
> * private:
> * * C c;
>
> };
>
> int main()
> {
> * D d;
> * d.foo1();
> * d.foo2();
> }

 
Reply With Quote
 
Vladimir Jovic
Guest
Posts: n/a
 
      05-11-2010
Öö Tiib wrote:
> On May 11, 9:23 am, vj <(E-Mail Removed)> wrote:
>
>> How to change the example, to make it compile?

>
> Either rename one of the functions from ambiquous candidate set
> (compiler very nicely explains what these are) or make it explicit
> what it is that you are calling by qualifying the called function.
>


But what if that is not an option? For example, instead of having
methods named boo, A requires non-const operator[], and B requires const
operator[]

Alf's response in else-thread was right on the target
 
Reply With Quote
 
Vladimir Jovic
Guest
Posts: n/a
 
      05-11-2010
Alf P. Steinbach wrote:
> On 11.05.2010 08:23, * vj:

<snip>
> The error is apparently caused by the possible boo's coming from
> different classes, at some point before their signatures are considered.
>
> I think you can find the relevant sections of the standard yourself, but
> as a practical matter, put
>
> using A::boo;
> using B::boo;
>
> in the public section of your C class.
>
> Then (apparently) the compiler is happy to also consider the signatures,
> and discovers that one of them is a better match.
>


Right. Thank you
 
Reply With Quote
 
Öö Tiib
Guest
Posts: n/a
 
      05-11-2010
On May 11, 12:26*pm, Vladimir Jovic <(E-Mail Removed)> wrote:
> Öö Tiib wrote:
> > On May 11, 9:23 am, vj <(E-Mail Removed)> wrote:

>
> >> How to change the example, to make it compile?

>
> > Either rename one of the functions from ambiquous candidate set
> > (compiler very nicely explains what these are) or make it explicit
> > what it is that you are calling by qualifying the called function.

>
> But what if that is not an option? For example, instead of having
> methods named boo, A requires non-const operator[], and B requires const
> operator[]


Best practice rules i currently have to follow consider it a design
bug when non-const operator[] is provided and const operator[] is not
provided. It i think makes sense, too.

> Alf's response in else-thread was right on the target


Yes, i forgot to say that using declarations also help compiler to
concentrate better (but do not help imaginary newbie reading the
code). Alf posted recently (even more complex for me) problem where
most ruling compilers did not find matching template despite using
directive was used. There also using declaration was one way to
resolve the problem.
 
Reply With Quote
 
Vladimir Jovic
Guest
Posts: n/a
 
      05-11-2010
Öö Tiib wrote:
> On May 11, 12:26 pm, Vladimir Jovic <(E-Mail Removed)> wrote:
>> Öö Tiib wrote:
>>> On May 11, 9:23 am, vj <(E-Mail Removed)> wrote:
>>>> How to change the example, to make it compile?
>>> Either rename one of the functions from ambiquous candidate set
>>> (compiler very nicely explains what these are) or make it explicit
>>> what it is that you are calling by qualifying the called function.

>> But what if that is not an option? For example, instead of having
>> methods named boo, A requires non-const operator[], and B requires const
>> operator[]

>
> Best practice rules i currently have to follow consider it a design
> bug when non-const operator[] is provided and const operator[] is not
> provided. It i think makes sense, too.


I agree for a general case, but there are cases when the non-const
operator[] is not needed, and using it is an error. What to do in that
case? Throw an exception?
Having the static analysis fail (compiling error) is better then doing a
run-time check.

For example, a device writes data to a buffer in memory. If this data
should not be modified (only read), using non-const operator[] to access
that memory is wrong, no?
(I know I would need volatile in this example, but that is another story)
 
Reply With Quote
 
Öö Tiib
Guest
Posts: n/a
 
      05-11-2010
On May 11, 2:21*pm, Vladimir Jovic <(E-Mail Removed)> wrote:
> Öö Tiib wrote:
> > On May 11, 12:26 pm, Vladimir Jovic <(E-Mail Removed)> wrote:
> >> Öö Tiib wrote:
> >>> On May 11, 9:23 am, vj <(E-Mail Removed)> wrote:
> >>>> How to change the example, to make it compile?
> >>> Either rename one of the functions from ambiquous candidate set
> >>> (compiler very nicely explains what these are) or make it explicit
> >>> what it is that you are calling by qualifying the called function.
> >> But what if that is not an option? For example, instead of having
> >> methods named boo, A requires non-const operator[], and B requires const
> >> operator[]

>
> > Best practice rules i currently have to follow consider it a design
> > bug when non-const operator[] is provided and const operator[] is not
> > provided. It i think makes sense, too.

>
> I agree for a general case, but there are cases when the non-const
> operator[] is not needed, and using it is an error. What to do in that
> case? Throw an exception?


Only const is ok. The rules i follow say that sole non-const operator
[] is error.

> Having the static analysis fail (compiling error) is better then doing a
> run-time check.


Yes, most things that policies require are best to detect with static
analysis tools if possible. It saves lot of time of reviewers, also
new people pick up rules enforced by tools quicker and with less
problems or hard feelings. Tools give the feedback fast and it really
is not weakening the language at all when some obscure practices are
forbidden.

> For example, a device writes data to a buffer in memory. If this data
> should not be modified (only read), using non-const operator[] to access
> that memory is wrong, no?
> (I know I would need volatile in this example, but that is another story)


For ensuring that you use non-const operator [] ... define const
reference to your container that enwraps the buffer and use it.
Compilers optimize worthless additional indirections usually out. Yes,
volatile is usually used when the memory location may be read/written
by external hardware.
 
Reply With Quote
 
Öö Tiib
Guest
Posts: n/a
 
      05-11-2010
On May 11, 3:11*pm, Öö Tiib <(E-Mail Removed)> wrote:
> On May 11, 2:21*pm, Vladimir Jovic <(E-Mail Removed)> wrote:
>
>
>
>
>
> > Öö Tiib wrote:
> > > On May 11, 12:26 pm, Vladimir Jovic <(E-Mail Removed)> wrote:
> > >> Öö Tiib wrote:
> > >>> On May 11, 9:23 am, vj <(E-Mail Removed)> wrote:
> > >>>> How to change the example, to make it compile?
> > >>> Either rename one of the functions from ambiquous candidate set
> > >>> (compiler very nicely explains what these are) or make it explicit
> > >>> what it is that you are calling by qualifying the called function.
> > >> But what if that is not an option? For example, instead of having
> > >> methods named boo, A requires non-const operator[], and B requires const
> > >> operator[]

>
> > > Best practice rules i currently have to follow consider it a design
> > > bug when non-const operator[] is provided and const operator[] is not
> > > provided. It i think makes sense, too.

>
> > I agree for a general case, but there are cases when the non-const
> > operator[] is not needed, and using it is an error. What to do in that
> > case? Throw an exception?

>
> Only const is ok. The rules i follow say that sole non-const operator
> [] is error.
>
> > Having the static analysis fail (compiling error) is better then doing a
> > run-time check.

>
> Yes, most things that policies require are best to detect with static
> analysis tools if possible. It saves lot of time of reviewers, also
> new people pick up rules enforced by tools quicker and with less
> problems or hard feelings. Tools give the feedback fast and it really
> is not weakening the language at all when some obscure practices are
> forbidden.
>
> > For example, a device writes data to a buffer in memory. If this data
> > should not be modified (only read), using non-const operator[] to access
> > that memory is wrong, no?
> > (I know I would need volatile in this example, but that is another story)

>
> For ensuring that you use non-const operator [] ... define const

do not use ^^^
> reference to your container that enwraps the buffer and use it.
> Compilers optimize worthless additional indirections usually out. Yes,
> volatile is usually used when the memory location may be read/written
> by external hardware.- Hide quoted text -



 
Reply With Quote
 
 
 
Reply

Thread Tools

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 On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Derived Structure in Derived Class?? David C++ 3 01-29-2008 07:38 AM
Derived::Derived(const Base&) and Derived& operator=(const Base&) developereo@hotmail.com C++ 1 05-23-2007 01:44 PM
Derived::Derived(const Base&) developereo@hotmail.com C++ 4 05-23-2007 09:32 AM
Derived::Derived(const Base&) and Derived& operator=(const Base&) developereo@hotmail.com C++ 1 05-23-2007 12:07 AM
base/derived ambiguity with gcc, but not with MSVC =?ISO-8859-1?Q?Christian_Engstr=F6m?= C++ 2 02-12-2004 09:15 AM



Advertisments