C ++模板回调去抖功能

时间:2015-02-14 17:44:26

标签: c++ templates

我一直试图想出一个模板化的函数,它在处理使用函数指针回调的C API时概括了反弹过程。

我大部分都认为它有一个工作系统,但我想知道是否有办法清理最后一步。

想象一下,你有一个API,它接受一个函数指针和一个用户数据指针。您希望使用实例方法作为回调目标。这需要一个“反弹”功能,将用户数据指针重新解释为实例指针,并使用其余参数调用该方法。

以下示例代码有效:

#include <cstdio>

class Foo {
public:
    Foo(int val) : val_(val) { }

    void baz(int v) const
    {
        printf("baz %d\n", v + val_);
    }

private:
    int val_;
};

// Templated bounce function
template<class T, class Method, Method m, class Ret, class ...Args>
static Ret bounce(void *priv, Args... args)
{
    return ((*reinterpret_cast<T *>(priv)).*m)(args...);
}

#define BOUNCE(c, m) bounce<c, decltype(&c::m), &c::m>

// Callback simulator
void call_callback(void (*func)(void *, int), void *priv, int v)
{
    if (func) {
        func(priv, v);
    }
}

// Main Entry
int main()
{
    Foo bar(13);

    call_callback(&bounce<Foo, decltype(&Foo::baz), &Foo::baz>, &bar, 10);
    call_callback(&BOUNCE(Foo, baz), &bar, 11);

    return 0;
}

基本上我正在寻找一种清理用法的方法。宏工作,但我试图找到一些类型的辅助函数,可以只采取像&Foo::baz这样的方法指针参数,并推导出所有参数。类似于bounce_gen(&Foo::baz)的东西会返回指向实际反弹函数的指针。

这是一项有趣的练习,但我无法完成最后一部分。

1 个答案:

答案 0 :(得分:0)

成员函数指针的类型包含类类型和函数签名。因此,您可以让模板函数参数推导为您处理:

template<class T, class Method, class ...Args>
static auto bounce(Method T::*func, T* priv, Args... args) -> decltype((priv->*m)(args...))
{
    return (priv->*m)(args...);
}

更方便的可能是使用std::bind或lambda来完全隐藏它是成员函数调用的事实:

template<class Func, class ...Args>
static auto bounceCallable(Func func, Args... args) -> decltype(func(args...))
{
    return func(args...);
}

你会这样称呼它:

call_callback([&bar](int v){bar.baz(v);}, 11);

使用lambda,你的语法比使用std::bind更好,但它的代价是不得不重复签名。