在纯C ++中扩充类/应用方面(C ++ 11)

时间:2013-08-06 08:15:37

标签: c++ c++11 aop aspect

假设我有一个班级:

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

    int computeAnswer() {
        return -42;
    };

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

它执行一些计算,可以做任何想做的事。

现在我想补充它 - 应用一个方面,比如记录每个方法调用。

如果我手动实现这个,我会以这种方式实现所有方法:

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

我希望解决方案尽可能通用(我不想手动转发所有电话),因此可能的用法可能包括其中一种(以可能的为准)< / p>

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.

这样当我打电话时

 int result =  w.computeAnswer();

将记录通话。也许新的省略号运算符(...)可以在这里派上用场?

2 个答案:

答案 0 :(得分:6)

这不是直接可行的,因为您无法检查类以查看它具有哪些成员。

但是,你可以做一些接近的事情:

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

Logging::operator()如下所示:

/* 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;
}

对于完全通用的代码,它不会比这更好,因为C ++没有(静态)反射。

答案 1 :(得分:2)

扩展Xeo的答案,如果你使用decltyperesult_of而不是auto &&,你也可以获得副本删除。

template<typename F>
auto operator()(F &&f) -> decltype(std::forward<F>(f)(wrapped))
{
    pre_log();
    decltype(std::forward<F>(f)(wrapped)) result = std::forward<F>(f)(wrapped);
    post_log(result);
    return result;
}

在C ++ 14中,您可以将其缩短为:

template<typename F>
decltype(auto) operator()(F &&f)
{
    pre_log();
    decltype(auto) result = std::forward<F>(f)(wrapped);
    post_log(result);
    return result;
}