C++ compiler error involving private inheritance
Asked Answered
V

3

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?

Viceregal answered 10/2, 2012 at 5:28 Comment(3)
Unrelated to the problem, What does C(A<B>) mean here?Upward
@fizzbuzz: Constructor taking an A<B> by value.Pneumatophore
@Xeo, oh yes, A<B> is just a type.Upward
P
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...

Pneumatophore answered 10/2, 2012 at 5:35 Comment(4)
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...Pneumatophore
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?Viceregal
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.Pneumatophore
I also opened up a follow-up question.Pneumatophore
C
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 () {
}
Cliffordclift answered 10/2, 2012 at 5:44 Comment(0)
D
-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.

Dobruja answered 10/2, 2012 at 5:32 Comment(3)
Wrong, A<B> has to construct the B base subobject, and it's accessible there.Pneumatophore
What is B::B? B's implicitly declared default constructor?Viceregal
@HighCommander B::B is the implicitly declared default constructor that is made private in A<B>.Dobruja

© 2022 - 2024 — McMap. All rights reserved.