Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesnt this code compile?

I got a situation like this:

struct Foo
{
    void Barry() { }
};

struct Bar : private Foo
{
    template <class F> void Bleh(F Func) { Func(); }
};

struct Fooey : public Bar
{
    void Blah() { Foo f; Bar::Bleh(std::bind(&Foo::Barry, &f)); }
};

And it doesn't compile (g++ 4.7.3). With error:

test.cpp: In member function ‘void Fooey::Blah()’:
test.cpp:4:1: error: ‘struct Foo Foo::Foo’ is inaccessible
test.cpp:15:23: error: within this context
test.cpp:4:1: error: ‘struct Foo Foo::Foo’ is inaccessible
test.cpp:15:47: error: within this context

However, if I do this:

class Fooey;
void DoStuff(Fooey* pThis);

struct Fooey : public Bar
{
    void Blah() { DoStuff(this); }
};

void DoStuff(Fooey* pThis)
{
    Foo f;
    pThis->Bleh(std::bind(&Foo::Barry, &f));
}

It compiles just fine. What is logic behind this?

like image 748
Mislav Blažević Avatar asked Sep 20 '26 04:09

Mislav Blažević


2 Answers

Here

struct Fooey : public Bar
{
    void Blah() { Foo f; Bar::Bleh(std::bind(&Foo::Barry, &f)); }
};

name lookup for Foo finds the base class of Bar which is inaccesible because Bar inherits privately.

To fix it, qualify the name fully:

    void Blah() { ::Foo f; Bar::Bleh(std::bind(&::Foo::Barry, &f)); }
like image 162
jrok Avatar answered Sep 21 '26 19:09

jrok


The problem is that, inside Foo or any class derived from it, Foo is the injected class name; a name scoped inside Foo, which hides the same name for the class in the enclosing namespace. In this case, that is inaccessible due to the private inheritance.

You can work around this by explicitly referring to the name in the namespace, in this case ::Foo. Unfortunately, that will break if you move the class into another namespace.

like image 40
Mike Seymour Avatar answered Sep 21 '26 18:09

Mike Seymour



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!