C++ "simple"具有任意参数和返回值的函数的函数回调

标签 c++ callback compiler-errors profiling function-pointers

我正在尝试创建一个简单的函数计时器/分析器。我的主要目标是创建一个可以快速、轻松且不显眼地添加到我想要分析的任何函数调用中的函数。

例如,要分析foobarbaz 我想要一个ft(函数timer) 函数,可以做以下事情,尽可能少的影响原来的代码:

ft(foo());
ft(bar(1, 2, 3));
int result = ft(baz());
string result = ft(qux("a", 2, 3.4));

请注意,对于 bazqux,从 ft 返回的结果应该是函数本身返回的结果。

ft 处理所有的计时和日志记录等。

我遇到过几个线程,它们提到如何为具有任意参数的函数执行函数回调,但甚至没有提到如何处理返回值。

这是最接近的:Variable number of arguments (va_list) with a function callback?但是在尝试处理 void 函数以及返回值的函数时,我陷入了困境。

我开始认为使用宏是执行此操作的方法,但也许有更好的方法。

这是我目前的微弱尝试(删节):

static Timer fTimer;

class VoidFuncBase
{
public:
  virtual void operator()() = 0;
};

class VoidFuncWrapper0 : public VoidFuncBase
{
public:
  typedef void (*func)();
  VoidFuncWrapper0(func fp) : fp_(fp) { }
  void operator()() { fp_(); }
private:
  func fp_;
};

template<typename P1>
class VoidFuncWrapper1 : public VoidFuncBase
{
public:
  typedef void (*func)(const P1 &);
  VoidFuncWrapper1(func fp, const P1 &p1) : fp_(fp), p1_(p1) { }
  void operator()() { fp_(p1_); }
private:
  func fp_;
  P1 p1_;
};

template<typename P1, typename P2>
class VoidFuncWrapper2 : public VoidFuncBase
{
public:
  typedef void (*func)(const P1 &, const P2 &);
  VoidFuncWrapper2(func fp, const P1 &p1, const P2 &p2)
    : fp_(fp), p1_(p1), p2_(p2) { }
  void operator()() { fp_(p1_, p2_); }
private:
  func fp_;
  P1 p1_;
  P2 p2_;
};

template<typename R>
class FuncBase
{
public:
  virtual R operator()() = 0;
};

template<typename R>
class FuncWrapper0 : public FuncBase<R>
{
public:
  typedef R (*func)();
  FuncWrapper0(func fp) : fp_(fp) { }
  R operator()() { return fp_(); }
private:
  func fp_;
};

template<typename R, typename P1>
class FuncWrapper1 : public FuncBase<R>
{
public:
  typedef R (*func)(const P1 &);
  FuncWrapper1(func fp, const P1 &p1) : fp_(fp), p1_(p1) { }
  R operator()() { return fp_(p1_); }
private:
  func fp_;
  P1 p1_;
};

template<typename R, typename P1, typename P2>
class FuncWrapper2 : public FuncBase<R>
{
public:
  typedef R (*func)(const P1 &, const P2 &);
  FuncWrapper2(func fp, const P1 &p1, const P2 &p2)
    : fp_(fp), p1_(p1), p2_(p2) { }
  R operator()() { return fp_(p1_, p2_); }
private:
  func fp_;
  P1 p1_;
  P2 p2_;
};

template<typename R>
R ft(FuncBase<R> func, std::string functionName)
{
    unsigned long threadId = getThreadId();
    double startTimeMs = fTimer.getMilliseconds();

    R result = func();

    double duration = fTimer.getMilliseconds() - startTimeMs;
    logf("%u %s took %fms", threadId, functionName.c_str(), duration);

    return result;
}

void ft(VoidFuncBase func, std::string functionName, int logTimeoutMs)
{
    unsigned long threadId = getThreadId();
    double startTimeMs = timer.getMilliseconds();

    func();

    double duration = timer.getMilliseconds() - startTimeMs;
    logf("%u %s took %fms", threadId, functionName.c_str(), duration);
}

目前我得到

"error: cannot declare parameter 'func' to be of abstract type 'VoidFuncBase'".

但无论如何,我可能正朝着错误的方向前进。

最佳答案

可变参数模板是要走的路!在任何情况下,您都需要稍微更改函数的调用方式:

template <typename R, typename... T, typename... A>
R ft(R (*f)(T...), A&&... a) {
    // do you business
    return f(std::forward<A>(a)...);
}

int r0 = ft(&baz);
int r1 = ft(&qax, a, b, c);

不过,当函数重载时,事情会变得有趣。请注意,调用后的任何处理都会进入调用前设置的对象的析构函数。

关于C++ "simple"具有任意参数和返回值的函数的函数回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9634775/

相关文章:

c++ - GCC 匿名未初始化

c++ - 错误消息/用户输入数字的 vector

c++ - 使用 std::vector 的指数内存消耗增长

Python tkinter 文本修改回调

c++ - 你能全局设置 qDebug() 浮点精度和数字格式吗?

c++ - 回调 lambda 到 std::function 0xCCCCCCCC

javascript - 不需要参数的回调 - 为什么?

compiler-errors - SML代码并且无法编译,要求andalso

c++ - 如何实例化 std::exception_ptr 以进行单元测试

java - 服务器设计与实现