Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is a C++ template able to "forward any class function" from parent class?

class Foo {
public:
  void methodA();
};

class ManagedFoo {
Foo fooInst;
public:
  void methodA() { doSomething(); fooInst.methodA();}
};

Now I want to make ManagedFoo as a template, managing any class not only Foo, and before any of Foo's function is called, call doSomething first.

template<typename _TyManaged>
class Manager {
  _TyManaged _managedInst;
  void doSomething();
public:
  /*Forward every function called by _managedInst*/
  /*How to write this?*/
};

I want to make it the same, make it replaceable between this two class, like this :

Foo* foo = new Foo();
foo->methodA();

Manager<Foo> managedFoo = new Manager<Foo>();
managedFoo->methodA(); //Hope it call Manager::doSomething() first then call _managedInst.methodA();

Can C++11 template do such thing? if answer is yes, how to?

like image 478
Rayer Avatar asked Jan 10 '14 06:01

Rayer


3 Answers

Solution based on operator-> overloading:

#include <iostream>
#include <memory>

class A {
public:
    void foo() { std::cout << "foo\n"; }
    void bar() { std::cout << "bar\n"; }
};

template <typename T>
class ManagedBase {
    std::shared_ptr<T> _inst;
public:
    ManagedBase(const std::shared_ptr<T> inst) : _inst(inst) { }
    virtual ~ManagedBase() { }

    std::shared_ptr<T> operator->() {
        before();
        return this->_inst;
    }

    virtual void before() =0;
};


template <typename T>
class ManagedPrint : public ManagedBase<T> {
public:
    ManagedPrint(const std::shared_ptr<T> inst) : ManagedBase(inst) { }

    virtual void before() {
        std::cout << "Said: ";
    }
};


int main() {
    auto ma = ManagedPrint<A>(std::make_shared<A>());
    ma->bar();      // Said: foo
    ma->bar();      // Said: bar
}
like image 131
Alexander Mihailov Avatar answered Oct 23 '22 13:10

Alexander Mihailov


Something like this?

template<typename _TyManaged>
class Manager {
  _TyManaged _managedInst;
  void doSomething();
public:
  _TyManaged* operator->() {
    doSomething();
    return &_managedInst;
  }
};
like image 3
dalle Avatar answered Oct 23 '22 12:10

dalle


This can solve your problem. But I'm still not sure what you want to do with your Manager class.

class Foo {
  public:
    void methodA();
};

template<typename T>
class ManagedFoo : public T {
  public:
    // some further extensions
};

And of course in this way you change the semantic of the Foo class by the manager from:
It has a
to
It is a
So I'm not sure if this is true in your case.

like image 2
frank Avatar answered Oct 23 '22 11:10

frank