[bug] typedefed base class not visible [VC8 RTM.050727-4200]

  • Thread starter Fernando Cacciola
  • Start date
F

Fernando Cacciola

Hi people,

I'm testing

Microsoft Visual Studio 2005
Version 8.0.50727.42 (RTM.050727-4200)

with our code base.

I'm getting lots of errors on code that compiled fine in 7.1.
Most of it boils down to the following new compiler bug:

struct A
{
int foo() const { return 1; }
};

struct B : A
{
typedef A base ;
};

struct D : B
{
} ;

int main(int argc, char* argv[])
{
B b ;
D d ;
int r0 = b.base::foo();
int r1 = d.base::foo(); // error C2039: 'A' : is not a member of 'D'

return 0;
}

As you can see, vc8 can't see the type B::base, which is A, from D.

Worst.. I get the same error even if D is defined as:

struct D : B
{
typedef B::base base ;
} ;

which explicitely redeclares B::base within D

I can of course do something like

struct D : B
{
typedef B Base ;
} ;

and then change the client code from

d.base::foo()

to

d.Base::base::foo()

which compiles OK, but I'd really hate to need to refactor ALL client code..
any ideas?

TIA
 
T

Tamas Demjen

Fernando said:
I'm getting lots of errors on code that compiled fine in 7.1.
Most of it boils down to the following new compiler bug:

struct A
{
int foo() const { return 1; }
};

struct B : A
{
typedef A base ;
};

I think the new compiler is right, 7.1 is wrong, and the problem is in
your code. You're doing private inheritance. By writing

struct B : A

you are essencially making foo() invisible. You should try

struct B : public A

Tom
 
F

Fernando Cacciola

Tamas said:
Fernando Cacciola wrote:

I think the new compiler is right, 7.1 is wrong, and the problem is in
your code. You're doing private inheritance. By writing

struct B : A

you are essencially making foo() invisible.
No. Is public inheritance because B is struct, not a class.

Test the code in

http://www.comeaucomputing.com/tryitout/

to see it's well-formed.

Comeau C++ is-and has always been-the best reference for testing std
conformance.
 
D

Doug Harrison [MVP]

Hi people,

I'm testing

Microsoft Visual Studio 2005
Version 8.0.50727.42 (RTM.050727-4200)

with our code base.

I'm getting lots of errors on code that compiled fine in 7.1.
Most of it boils down to the following new compiler bug:

struct A
{
int foo() const { return 1; }
};

struct B : A
{
typedef A base ;
};

struct D : B
{
} ;

int main(int argc, char* argv[])
{
B b ;
D d ;
int r0 = b.base::foo();
int r1 = d.base::foo(); // error C2039: 'A' : is not a member of 'D'

return 0;
}

As you can see, vc8 can't see the type B::base, which is A, from D.

I think it's probably a bug, and you can report it here:

http://lab.msdn.microsoft.com/productfeedback/Default.aspx

Comeau does like it, a lot more than I'm liking trying to figure this out
from reading the standard, anyway. :)
Worst.. I get the same error even if D is defined as:

struct D : B
{
typedef B::base base ;
} ;

which explicitely redeclares B::base within D

I can of course do something like

struct D : B
{
typedef B Base ;
} ;

and then change the client code from

d.base::foo()

to

d.Base::base::foo()

which compiles OK, but I'd really hate to need to refactor ALL client code..
any ideas?

That's not the nicest syntax, so I'd have to wonder why you're doing things
this way. What happens if someone says d.foo() instead of d.base::foo()?
Would it be appropriate for B to bring A::foo into scope with a
using-declaration, so that if would overload with B::foo? If not, what
about introducing a forwarding function A_foo into B?
 
F

Fernando Cacciola

Doug said:
On Thu, 3 Nov 2005 15:04:08 -0300, "Fernando Cacciola"

I think it's probably a bug, and you can report it here:

http://lab.msdn.microsoft.com/productfeedback/Default.aspx

OK. I'll do it.
That's not the nicest syntax, so I'd have to wonder why you're doing
things this way. What happens if someone says d.foo() instead of
d.base::foo()? Would it be appropriate for B to bring A::foo into
scope with a using-declaration, so that if would overload with
B::foo? If not, what about introducing a forwarding function A_foo
into B?

Well, what I posted was a simplified version of the actual code.
Anyway, this comes from something that once ocurred to me to be a good
idea.. I'm not sure anymore it really is.. still, I used it a lot those days
and it just linger there in this rather old code base.

I needed a way to offer a form of "late friendship", that is, a way to give
class A access to parts of class B "reserved for friends", but without
having B know about A (mainly becasue of the limitations of real friendship
between template classes)
A solution is to hide the reserved part of B, but only partially:

Consider the follow as part of some framework (or class library):

struct A
{
int foo() ;
}

class B : A
{
typedef A door ;

private:

int foo() ;
} ;

Framework users don't ever deal with A, only with B (that's the type exposed
by and documented in the framework), so b.foo() is "private" to them.
The framework itself, OTOH, gains access to foo() through the special
syntax: b.door::foo();

Of course, nothing prevents a framework user to "discover the door" and use
it, so the whole technique is probably just nonsense; but I have to live
with it now ;)

As you can see, the whole idea is to require the user code to explicitely
walk through the base class to get access to the "reserved" interface.


NOTE: FWIW, I discover this techique in the CGAL library www.cgal.org, is
not my invention.

Best
 
T

Tamas Demjen

Fernando said:
No. Is public inheritance because B is struct, not a class.

Sorry, you're right, I was way off. I should've tried it before posting.

I discovered a workaround, I don't know if it works for you though:

struct D : B
{
typedef B base; // <-- add this line
} ;

Tom
 
Top