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

C++ 在纯C+中扩充类/应用方面+;(C+;+;11),c++,c++11,aop,aspect,C++,C++11,Aop,Aspect,假设我有一门课: class Widget { public: void initialize() { // hurr-durr }; int computeAnswer() { return -42; }; std::string getQuestion() { return "The question"; }; }; 它执行一些计算,可以做任何它想做的事情 现在我想扩充它——应用一个方面,比

假设我有一门课:

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

这些电话将被记录下来。也许新的省略号操作符(
)可以在这里派上用场?

这不可能直接实现,因为您无法检查类以查看它有哪些成员

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

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

<> P>完全通用代码的情况不会比这更好,因为C++没有(静态)反射。

< p>在XEO的答案上扩展,如果使用<代码> DECKEXTION/<代码>或<代码> > <代码> >而不是<代码> 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;
}
模板
自动运算符()(F&&F)->decltype(std::forward(F)(包装))
{
pre_log();
decltype(std::forward(f)(wrapped))结果=std::forward(f)(wrapped);
事后日志(结果);
返回结果;
}
在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;
}
模板
decltype(自动)运算符()(F&&F)
{
pre_log();
decltype(自动)结果=std::forward(f)(已包装);
事后日志(结果);
返回结果;
}

Decorator模式这很好。我相信一个好的宏可以隐藏lambda表达式的很大一部分。。
/* 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;
}
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;
}
template<typename F>
decltype(auto) operator()(F &&f)
{
    pre_log();
    decltype(auto) result = std::forward<F>(f)(wrapped);
    post_log(result);
    return result;
}