可以禁止演员吗?

时间:2020-08-03 19:58:43

标签: c++

上下文:

我一直在尝试使用this answer中的DietmarKühl的委托类,这种方式只有所有者类可以激活它,而我几乎实现了。

代码如下:

// Example program
#include <algorithm>
#include <iostream>
#include <memory>
#include <utility>
#include <vector>

class Entity;

struct EvArgs {
    Entity* Origin;
    EvArgs(){
    }
};

template <typename Signature>
struct delegate;

template <typename Args>
struct delegate<void(Args*)>
{
    struct base {
        virtual ~base() {}
        virtual void do_call(Args* args) = 0;
    };

    template <typename T>
    struct call : base {
        T d_callback;

        template <typename S>
        call(S&& callback) : d_callback(std::forward<S>(callback)) {}

        void do_call(Args* args) {
            this->d_callback(std::forward<Args*>(args));
            return;
        }
    };

    std::vector<std::unique_ptr<base>> d_callbacks;
    std::vector<std::unique_ptr<base>> d_tmp_callbacks;

    delegate(delegate const&) = delete;
    void operator=(delegate const&) = delete;
public:
    delegate() {
        if (!std::is_base_of<EvArgs, Args>::value)
            throw "specified type is not derived class from EvArgs\n";
    }
    ~delegate() {
        d_callbacks.clear();
        d_tmp_callbacks.clear();
    }

    template <typename T>
    delegate& operator+= (T&& callback) {
        this->d_callbacks.emplace_back(new call<T>(std::forward<T>(callback)));
        return *this;
    }
    template <typename T>
    delegate& operator<< (T&& callback) {
        this->d_tmp_callbacks.emplace_back(new call<T>(std::forward<T>(callback)));
        return *this;
    }
};

template<typename Signature>
struct action_delegate;

template<typename Args>
struct action_delegate<void(Args*)> : public delegate<void(Args*)>{
    delegate<void(Args*)>& getBase(){
        return *static_cast<delegate<void(Args*)>*>(this);
    }
    
    void operator()(Args* args) {
        for (auto& callback : this->d_callbacks)        callback->do_call(args);
        for (auto& callback : this->d_tmp_callbacks)    callback->do_call(args);
        this->d_tmp_callbacks.clear();

        delete args;
    }
};

class instance{
private:
    action_delegate<void(EvArgs*)> _collision;
public:
    delegate<void(EvArgs*)>& collision = _collision.getBase();
};


int main(){
    instance i;
    i.collision << [](EvArgs* a){
        std::cout << "random calling\n";
        };

    //i want to prohibit this:
    (static_cast< action_delegate<void(EvArgs*)>& >(i.collision))(new EvArgs());
}

问题:

由于action_delegate是私有成员,因此只有instance类可以使用operator()调用其激活。并且由于delegate是公开的,因此operator <<()operator +=()可以在课堂之外访问。

问题在于,有一种方法可以将delegate强制转换为action_delegate,因此可以在类外使用operator()激活委托。我真的想避免这种情况。

此概念的原始创建者可以通过评论正文开头的链接访问。

0 个答案:

没有答案