Inheriting both class template and the template paraemeter

Viewed 88

Suppose we have the following template class, inspired by std::shared_ptr (ignore bad memory management for simplicity):

template <class C> class shared_class {
public:
  const shared_class& operator=(const shared_class& rhs) {
    ptr = rhs.ptr;
    refs[ptr] += 1;
    return *this;
  }

  C* data() { return ptr; }

protected:
  shared_class() {
    if (ptr == nullptr)
      ptr = new C;
    refs[ptr] = 1;
  }
  shared_class(const shared_class& other) {
    ptr = other.ptr;
    refs[ptr] += 1;
  }
  ~shared_class() {
    if ((refs[ptr] -= 1) == 0) {
      refs.erase(ptr);
      delete ptr;
    }
  }

private:
  static std::unordered_map<C*, size_t> refs;
  C* ptr = nullptr;
};

template <class C> std::unordered_map<C*, size_t> shared_class<C>::refs = {};

I would like to use it in the following way:

class A_data {
protected:
  int foo = 50;

  friend class A;
  friend class shared_class<A_data>;
};

class A : protected shared_class<A_data> {
public:
  void foo(int f) { data()->foo = h; }
  int foo() { return data()->foo; }
};

using namespace std;

int main(){
  A a;
  A b = a;
  a.foo(40);
  cout << b.foo(); // 40
}

This works well, but now suppose I want to create a class that inherits A, but also inherits its data, such as this:

class B_data : public A_data {
  int bar = 100;

  friend class B;
  friend class shared_class<B_data> // Probably wrong
};

class B : public A {
  int bar() {
    return data()->bar(); // Error: no member 'bar' in A_data
  }
}

This is a problem, because the constructor in shared_class only knows how to allocate A_data. It seems to me that I am only able to decide on one form of inheritence: either I inherit the template class like above, or I can inherit a different shared_class template, like this:

class B_data : public A_data {
  int bar = 100;

  friend class B;
  friend class shared_class<B_data> // Now it's not wrong
};

class B : public shared_class<B_data> {
  int bar() {
    return data()->bar(); // Now it will work
  }
}

While this works, I lose relation to the A class, and am now unable to do use A::foo, forcing me to define it in B:

class B : public shared_class<B_data> {
  void foo(int f) { data()->foo = h; }
  int foo() { return data()->foo; }
  int bar() { return data()->bar(); }
}

Is there a (relatively elegant) way to make this work as though B inherits A while simultaneously B_data inherits A_data?

0 Answers
Related