Grizzly
Grizzly

Reputation: 20201

Accessing protected member of template parameter

I have a template class for which I need to access a protected member function of the template parameter, like this:

class Foo
{
protected:
    void foo() {}
};

template<typename T>
class Bar
{
public:
    static void bar(T& self){self.foo();}
};
...
Foo f;
Bar<Foo>::bar(f);

My problem is getting access to the protected method. I tried putting a friend class T into Bar, but that doesn't seem to be allowed in c++ (edit: and wouldn't solve my problem anyways, so it seemd). I tried letting Bar inherit from T (template<typename T> class Bar: public T (could have used private inheritance, but the public interface of Bar is not terribly important, since the class itself is internal only)), but that didn't allow for access of foo() either. So how do I get access to the foo() method?

Edit: Foo should not need to know Bar<Foo>, since there are quite a lot Bar classes. I can however make other changes to Foo (without changing the public interface of course).

Upvotes: 1

Views: 2601

Answers (4)

Yumiko
Yumiko

Reputation: 95

If you want to access a protected member a derived class of this, you can do it with the using keyword:

class A
{
protected:
  void i_am_protected () {}
};

template <class T>
class B : public T
{
  using T::i_am_protected;

  void call_me ()
  {
    i_am_protected(); // OK.
    this->i_am_protected(); // This compiles without the keyword.
  }
};

If you need B to access a protected member of A when an object is passed to B, you need to declare B as a friend of A:

class A
{
  template <class T>
  friend
  class B;

protected:
  void i_am_protected () {}
};

template <class T>
class B : public T
{
  void call_me (T& obj)
  {
    obj.i_am_protected(); // OK.
  }
};

Upvotes: 0

CB Bailey
CB Bailey

Reputation: 792557

OK, this is a "rot in hell" hack. You can abuse the fact that you can form pointers-to-members pointing to protected base members from a derived class.

class Foo
{
protected:
    void foo() {}
};

// Helper template to bypass protected access control
// for a member function called foo, taking no parameters
// and returning void.
template<typename T>
struct Unprotect : public T
{
    typedef void (T::*FooPtr)();
    static FooPtr GetFooPtr()
    {
        return &Unprotect::foo;
    }
};

template<typename T>
class Bar
{
public:
    static void bar(T& self){(self.*Unprotect<Foo>::GetFooPtr())();}
};

int main()
{
    Foo f;
    Bar<Foo>::bar(f);
}

Upvotes: 5

Jerry Coffin
Jerry Coffin

Reputation: 490398

You did your friend declaration in the wrong direction. If Bar says Foo is it's friend, that means Foo gets access to Bar's private data. For Bar to get access to Foo's private data, Foo has to say Bar is its friend.

Upvotes: 2

Mircea Ispas
Mircea Ispas

Reputation: 20790

template<typename T>
class Bar
{
public:
    static void bar(T& self){self.foo();}
};

class Foo
{
protected:
    void foo() {}
    friend class Bar<Foo>;
};

void main()
{
    Foo f;
    Bar<Foo>::bar(f);
}

Upvotes: 0

Related Questions