14
struct B {};
struct D : private B {
  B* fun () { return new D; }  // ok
}
struct DD : public D {
  B* foo () { return 0; } // error: ‘struct B B::B’ is inaccessible !
};

This error seems unreasonable to me. If we can use simple B* in global scope then why not in its privately derived classes? g++ demo.

We are Not trying to convert DD* to B*, which is forbidden by the language rules (this, this, this are related questions).
Note that, if I change B* foo() to int foo(), things go fine.

Community
  • 1
  • 1
iammilind
  • 68,093
  • 33
  • 169
  • 336

3 Answers3

7

So apparently the compiler thinks B is referring to the private constructor of B rather than the type.

Qualifying B apparently fixes that error:

class B* foo () { return 0; }

or this:

::B* foo () { return 0; }

I don't know why that's happening, but maybe this will help.


Update: maybe it's related to 11.2.4 of standard? The only problem is that my standardese isn't good enough to fully understand it.

(sorry for the image, copy/pasting isn't working for me)

Pubby
  • 51,882
  • 13
  • 139
  • 180
  • considering that 2 compilers are reporting the same error on 2 different platforms I think that is just something related to the standard or some important draft, probably about "name resolution". – user1797612 Dec 18 '12 at 06:30
  • @user1797612 Yeah, I agree. – Pubby Dec 18 '12 at 06:34
7

A quick look-up for injected-class-name in the Standard yields:

§11.1 [class.access.spec]

5/ [ Note: In a derived class, the lookup of a base class name will find the injected-class-name instead of the name of the base class in the scope in which it was declared. The injected-class-name might be less accessible than the name of the base class in the scope in which it was declared. —end note ]

[ Example:

class A { };
class B : private A { };
class C : public B {
    A *p; // error: injected-class-name A is inaccessible
    ::A *q; // OK
};

—end example ]

I believe this is eerily close to your example ;)


Note clang 3.0's stack, which is slightly more explicit:

$ clang++ -fsyntax-only test.cpp
test.cpp:6:5: error: 'B' is a private member of 'B'
    B* foo () { return 0; } // error: ‘struct B B::B’ is inaccessible !
    ^
test.cpp:2:12: note: constrained by private inheritance here
struct D : private B {
           ^~~~~~~~~
test.cpp:1:8: note: member is declared here
struct B {};
       ^
1 error generated.

Here we see that B is accessed through D, instead of directly picked up in the global namespace.

Community
  • 1
  • 1
Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
1

My best guess is that it's not forbidden, C++ simply doesn't see the B type inside that statement or in better terms the label B means nothing.

Some good read about

Community
  • 1
  • 1
user1797612
  • 812
  • 6
  • 22