Search code examples
c++c++11aopaspect

Augment a class / apply an aspect in pure C++ (C++11)


Suppose I have a class:

class Widget {
public:
    void initialize() {
        // hurr-durr
    };

    int computeAnswer() {
        return -42;
    };

    std::string getQuestion() {
        return "The question";
    };
};

It performs some computation, can do whatever it wants.

Now I want to augment it - apply an aspect, say one that logs each method call.

If I implemented this by hand, I'd implement all methods in this fashion:

  int LoggingWidget::computeAnswer(){
    log << 'Calling method computeAnswer';
    int result = Widget::computerAnswer();
    log << 'Result = ' << result;
    return result;
  }

I'd like the solution to be as generic as possible (I don't want to manually forward all calls), so the possible usages could include one of these (whichever is possible)

Widget* w = new LoggingWidget();  // either a class that inherits from Widget
                                  // and automatically forwards all calls.

Widget* w = new Logging<Widget>(); // or a template that does this.

so that when I call

 int result =  w.computeAnswer();

The calls will be logged. Perhaps the new ellipsis operator (...) could come in handy here?


Solution

  • This isn't directly possible, since you can't inspect a class to see which members it has.

    However, you can do something close:

    Logging<Widget> w(widget);
    w([&](Widget& w){
      return w.computeAnswer();
    });
    

    Where Logging::operator() looks like follows:

    /* somewhere in class: T wrapped; */
    
    template<class F>
    auto operator()(F&& f)
      -> decltype(f(wrapped))
    {
      pre_log();
      auto&& result = f(wrapped);
      post_log(result);
      return result;
    }
    

    It won't get better much better than this for totally generic code, since C++ has no (static) reflection.