c++ - 棘手的回调实现(C++)

标签 c++ c++11 lambda closures

我一直在想一个轻量级的类,它可以委托(delegate)静态/成员函数、仿函数、闭包等。在我的项目中,需要将这些实体作为函数参数传递,此外,还使用了this在其他一些情况下。

第一次,我决定使用模板和继承,结果是这样的:

template<class ReturnType, class ...Args>
class callback {
private:

    //
    struct abstract_invoker {
        virtual ReturnType invoke(Args...) = 0;
    };

    //
    template<class Function>
    class sf_invoker : public abstract_invoker {
    public:
        sf_invoker(Function function) : _function(function) { };

        ReturnType invoke(Args ...args) override {
            return _function(args...);
        }

    private:
        Function _function;
    };

    //
    template<class Class>
    class mf_invoker : public abstract_invoker {
        using Function = ReturnType (Class::*)(Args...);

    public:
        mf_invoker(Class& target, Function function) : _target(target), _function(function) { };

        ReturnType invoke(Args ...args) override {
            return (_target.*_function)(args...);
        }

    private:
        Class&      _target;
        Function    _function;
    };

// --------------------------------------
public:
    template<class Function>
    callback(Function function) {
        _invoker = new sf_invoker<Function>(function);
    }
    template<class Class>
    callback(Class& object, ReturnType(Class::*function)(Args...)) {
        _invoker = new mf_invoker<Class>(object, function);
    }
    ~callback() {
        delete _invoker;
    }

    ReturnType operator() (Args ...args) {
        return _invoker->invoke(args...);
    }

private:
    abstract_invoker* _invoker;
};

其实这个方法解决了我的问题,只是速度有点慢。我试图避免虚函数,根据经验发现下面的代码也能正常工作 (VS 2014):

template<class ReturnType, class ...Args>
class callback {
    using Function = ReturnType (*)(Args...);

public:
    template<class _Function>
    callback(_Function function) {
        auto invoker = [function] (Args ...args) -> ReturnType {
            return function(args...);
        };

        _invoker = &invoker;
    }
    template<class _Class>
    callback(_Class& object, ReturnType (_Class::*function)(Args...)) {
        auto invoker = [function, &object] (Args ...args) -> ReturnType {
            return (object.*function)(args...);
        };

        _invoker = &invoker;
    }

    ReturnType operator()(Args ...args) {
        return (*(Function*) _invoker)(args...);
    }

private:
    void* _invoker;
};

显然,此实现的运行速度更快。这样的方法是不安全的,但我不是很了解标准,所以我不知道lambda表达式的编译器要求。所以我的问题是:它有魔法吗?还是它适用于大多数编译器?

最佳答案

您的代码存在生命周期问题:您必须考虑对象有效的范围(以及之后它们就死了)。

template<class Func>
callback(Func function) {
    auto invoker = [function] (Args ...args) -> ReturnType {
        return function(args...);
    };

    _invoker = &invoker;
}

invoker 捕获状态,因此不能转换为指向函数的指针。如果 _invoker 被键入为 Function,编译器可能会警告您。

第二次重载同上。

所以,如果它起作用,那是偶然的。

关于c++ - 棘手的回调实现(C++),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22895300/

相关文章:

c++ - Ubuntu 中翻译快捷键

c++ - 虚拟方法会使应用程序变慢,但它们可以加快链接速度吗?

c++ - "Capture"lambda 函数中的变量解析为参数

c++ - 为什么定义析构函数会删除隐式定义的移动赋值运算符?

c++ - x 时间后如何中止 Winsock 连接

c++ - find_if 和 std::pair,但只有一个元素

c++ - ROS:在 nodehandle.subscribe 中使用 lambda 作为回调

r - 估计 Yeo 和 Johnson 变换的 Lambda

c++ - 没有实现文件 (.cpp) 的派生类

c++ - 在 64 位机器上构建 32 位 Qt 应用程序