6

Could someone please explain the following compiler error to me:

struct B
{
};

template <typename T>
struct A : private T
{
};

struct C : public A<B>            
{                                                                             
    C(A<B>);   // ERROR HERE
};

The error at the indicated line is:

test.cpp:2:1: error: 'struct B B::B' is inaccessible
test.cpp:12:7: error: within this context

What exactly is inaccessible, and why?

Aman Aggarwal
  • 3,905
  • 4
  • 26
  • 38
HighCommander4
  • 50,428
  • 24
  • 122
  • 194

3 Answers3

6

Try A< ::B> or A<struct B>.

Inside of C, unqualified references to B will pick up the so-called injected-class-name, it is brought in through the base class A. Since A inherits privately from B, the injected-class-name follows suit and will also be private, hence be inaccessible to C.

Another day, another language quirk...

Xeo
  • 129,499
  • 52
  • 291
  • 397
  • Good question. My answer looked like "Try `A< ::B>`. Why? Beats me..." at first. Now, the error message refers to `B::B`, the constructor, so that was about the only option. And no, I don't know why it tries to select a member function inside a template argument list... – Xeo Feb 10 '12 at 05:41
  • So, is this parsing quirk intentional, a compiler bug (unlikely since both GCC and Comeau give this error), or under/mis-specification of parsing in the standard? – HighCommander4 Feb 10 '12 at 05:50
  • 1
    All three MSVC, GCC and Clang spew this error, so it must be something in the spec.. I just asked on the llvm IRC channel, will report back. – Xeo Feb 10 '12 at 05:52
  • 2
    I also opened up a [follow-up question](http://stackoverflow.com/q/9223441/500104). – Xeo Feb 10 '12 at 06:04
4

The problem is name shielding of struct B . Check it out:

struct B{};

struct X{};

template <class T>
struct A : private T
{};

struct C : public A<B>
{
    C(){
          A<X> t1;     // WORKS
 //       A<B> t2;     // WRONG
          A< ::B> t3;  // WORKS
    }   
};

int main () {
}
Dmitriy Kachko
  • 2,804
  • 1
  • 19
  • 21
-1

You are making A privately inherit from B when you do A<B>, and that means that B::B is private so you can't construct a C.

Seth Carnegie
  • 73,875
  • 22
  • 181
  • 249