C++ Delegate模板类的设计

下面是一个C++ Delegate类的设计,可以支持绑定全局函数,类成员函数或lambda,lambda 大小需要小于等于24并且是trivial destructible

template<typename Signature>
class Delegate;

template<typename R, typename... Args>
class Delegate<R(Args...)> {

    typedef Delegate<R(Args...)> Self;

    [[noreturn]] static auto stub_null(void *, Args...) -> R {
        throw Exception("Bad AN::Delegate call");
    }

    typedef R (*stub_function)(void *, Args...);

    stub_function _stub = stub_null;
    void *_obj;
    char _method[16];
public:
    // Creates an unbound delegate
    Delegate() = default;

    Delegate(const Delegate &other)                     = default;
    auto operator=(const Delegate &other) -> Delegate & = default;

    explicit operator bool() const {
        return _stub != stub_null;
    }

    void unBind() {
        _stub = stub_null;
    }


    template<typename Func>
        requires std::is_trivially_destructible_v<Func> &&
                 (!std::is_pointer_v<Func>) &&
                 (sizeof(Func) <= sizeof _method + sizeof _obj) &&
                 std::is_invocable_v<Func, Args...> &&
                 std::same_as<std::invoke_result_t<Func, Args...>, R>
    void bind(Func &&func) {
        // copy or move construct
        new ((void *)&_obj) Func(std::forward<Func>(func));
        _stub      = [](void *self, Args... args) -> R {
            return std::invoke(*(Func *)&(((Self *)self)->_obj), std::forward<Args>(args)...);
        };
    }

    void bind(R(*func)(Args...)) {
        _obj       = (void *)func;
        _stub      = [](void *self, Args... args) -> R {
            return std::invoke((R(*)(Args...))((Self *)self)->_obj, std::forward<Args>(args)...);
        };
    }

    template<typename Func>
        requires (!std::same_as<Self, std::decay_t<Func>>)
    Self &operator = (Func &&func) {
        bind(std::forward<Func>(func));
        return *this;
    }

    template<typename Class>
    auto bind(const Class *cls, R(Class::*method)(Args...) const) -> void {
        _obj = (void *)cls;
        memcpy(_method, &method, sizeof method);
        static_assert(sizeof _method >= sizeof method);
        _stub = [](void *_self, Args... args) -> R {
            Self *self = (Self *)_self;
            return std::invoke(*(R(Class::**)(Args...) const)self->_method, (const Class *)self->_obj, std::forward<Args>(args)...);
        };
    }

    template<typename Class>
    auto bind(Class *cls, R(Class::*method)(Args...)) -> void {
        _obj = cls;
        memcpy(_method, &method, sizeof method);
        static_assert(sizeof _method >= sizeof method);
        _stub = [](void *_self, Args... args) -> R {
            Self *self = (Self *)_self;
            return std::invoke(*(R(Class::**)(Args...))self->_method, (Class *)self->_obj, std::forward<Args>(args)...);
        };
    }


    template<typename... UArgs,
             typename = std::enable_if_t<std::is_invocable_v<R(Args...), UArgs...>>>
    auto operator()(UArgs &&...args) const -> R {
        return _stub((void *)this, std::forward<UArgs>(args)...);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
C++中的委托(delegate)是一种函数指针的高级形式,它可以将函数作为参数传递给其他函数或存储在数据结构中。委托提供了一种灵活的方式来实现回调机制和事件处理。 在C++中,可以使用函数指针、函数对象和Lambda表达式来实现委托。下面是几种常见的委托用法: 1. 函数指针委托: 可以使用函数指针作为委托类型,将一个函数指针赋值给委托变量,然后通过委托变量调用相应的函数。 示例代码: ```cpp void Function1() { // 函数1的实现 } void Function2() { // 函数2的实现 } typedef void (*DelegateType)(); // 定义委托类型 int main() { DelegateType delegate = nullptr; delegate = &Function1; // 将函数1赋值给委托变量 delegate(); // 调用委托,实际上调用了函数1 delegate = &Function2; // 将函数2赋值给委托变量 delegate(); // 调用委托,实际上调用了函数2 return 0; } ``` 2. 函数对象委托: 可以使用函数对象(重载了函数调用运算符operator()的类对象)作为委托类型,将一个函数对象赋值给委托变量,然后通过委托变量调用相应的函数。 示例代码: ```cpp class FunctionObject { public: void operator()() { // 函数对象的实现 } }; int main() { FunctionObject functionObject; typedef void (FunctionObject::*DelegateType)(); // 定义委托类型 DelegateType delegate = nullptr; delegate = &FunctionObject::operator(); // 将函数对象的函数调用运算符赋值给委托变量 (functionObject.*delegate)(); // 调用委托,实际上调用了函数对象的函数调用运算符 return 0; } ``` 3. Lambda表达式委托: 可以使用Lambda表达式作为委托类型,直接将Lambda表达式赋值给委托变量,然后通过委托变量调用相应的函数。 示例代码: ```cpp int main() { auto lambda = []() { // Lambda表达式的实现 }; typedef decltype(lambda) DelegateType; // 定义委托类型 DelegateType delegate = lambda; // 将Lambda表达式赋值给委托变量 delegate(); // 调用委托,实际上调用了Lambda表达式 return 0; } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值