1

I have recently jumped into this whole world of classes, inheritance and templates in C++. But I got stuck. Please suggest me a way to solve this problem.

#include <iostream>

using namespace std;

template <typename type>
class a
{
protected:
  type *b;
};

template <typename type>
class p : public a<type>
{
public:
  void f()
  {
    type **q = &a<type>::b;
    cout << *q << endl; // some other code in reality related to (*q)
  }
};

int main()
{
  p<int> obj;
  obj.f();
  return 0;
}

But it turned out to be unsuccessful:

x.cpp: In instantiation of ‘void p<type>::f() [with type = int]’:
x.cpp:26:9:   required from here
x.cpp:9:9: error: ‘int* a<int>::b’ is protected
   type *b;
         ^
x.cpp:18:16: error: within this context
     type **q = &a<type>::b;
                ^
x.cpp:18:26: error: cannot convert ‘int* a<int>::*’ to ‘int**’ in initialization
     type **q = &a<type>::b;
                          ^

So I converted type **q = &a<type>::b; to type* a<type>::* q = &a<type>::b;. Then I got an additional error:

x.cpp: In instantiation of ‘void p<type>::f() [with type = int]’:
x.cpp:26:9:   required from here
x.cpp:9:9: error: ‘int* a<int>::b’ is protected
   type *b;
         ^
x.cpp:18:26: error: within this context
     type* a<type>::* q = &a<type>::b;
                          ^
x.cpp:19:13: error: invalid use of unary ‘*’ on pointer to member
     cout << *q;
             ^

So I converted b to a public: member of class a from protected:. But that too gives me an error:

x.cpp: In instantiation of ‘void p<type>::f() [with type = int]’:
x.cpp:26:9:   required from here
x.cpp:19:13: error: invalid use of unary ‘*’ on pointer to member
     cout << *q;
             ^

Now I cant perform further modifications. I would love to know if the original code does not tamper with the class's characteristics of being protected.

Compro Prasad
  • 162
  • 1
  • 14
  • `&a::b` is the special syntax to form a pointer-to-member. You can use `&(a::b)` to form a simple pointer. – Quentin Aug 22 '16 at 10:00
  • @iammilind Everything [looks fine](http://coliru.stacked-crooked.com/a/a97f5232e5a04c86) once the parentheses are added. – Quentin Aug 22 '16 at 10:03
  • @Quentin, yes I stand corrected. However, I felt that simply replacing with `(this->b)`, it solves the problem more diligently. And for this particular problem, there was no answer in the linked duplicate. I have re-closed the question again. Not sure, if I should delete my answer as it targets the specific problem. Hence retaining it, by giving benefit of doubt. – iammilind Aug 22 '16 at 10:11

1 Answers1

2

You can still live with protected: type *b;, if you change below line in your code:

type **q = &a<type>::b;  // `protected: b` is not accessible in this context

to

type **q = &(this->b);  // we make sure that `protected: b` is accessed here

In such case, you are actually treating b as the inherited protected member.


Why to use this for accessing base class?
Refer: In a templated derived class, why do I need to qualify base class member names with "this->" inside a member function?


Another way

Originally linked by @Quentin, below post suggests the difference between a simple pointer and pointer to member:
Pointer-to-member confusion

So, in your original question actually you were trying to get a pointer to member variable by following syntax:

&a<type>::b  ==> int* a<int>::*

while you probably wanted &(a<type>::b), which would result in simple int*.
So it's one of the notebook examples, showing the benefits of putting parenthesis at right place! :-)

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