假设我有一个班级:
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();
将记录通话。也许新的省略号运算符(...
)可以在这里派上用场?
答案 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的答案,如果你使用decltype
或result_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;
}