C++11 observer pattern (signals, slots, events, change broadcaster/listener, or whatever you want to call it)

前端 未结 5 1479
囚心锁ツ
囚心锁ツ 2021-01-30 04:41

With the changes made in C++11 (such as the inclusion of std::bind), is there a recommended way to implement a simple single-threaded observer pattern without depen

5条回答
  •  耶瑟儿~
    2021-01-30 05:06

    Here's what I came up with.

    This assumes no need to aggregate results from the listeners of a broadcast signal. Also, the "slot" or Signal::Listener is the owner of the callback. This ought to live with the object that your (I'm guessing...) lambda is probably capturing so that when that object goes out of scope, so does the callback, which prevents it from being called anymore.

    You could use methods described in other answers as well to store the Listener owner objects in a way you can lookup.

    template 
    class Signal
    {
        using fp = std::function;
        std::forward_list > registeredListeners;
    public:
        using Listener = std::shared_ptr;
    
        Listener add(const std::function &cb) {
            // passing by address, until copy is made in the Listener as owner.
            Listener result(std::make_shared(cb));
            registeredListeners.push_front(result);
            return result;
        }
    
        void raise(FuncArgs... args) {
            registeredListeners.remove_if([&args...](std::weak_ptr e) -> bool {
                if (auto f = e.lock()) {
                    (*f)(args...);
                    return false;
                }
                return true;
            });
        }
    };
    

    usage

    Signal bloopChanged;
    
    // ...
    
    Signal::Listener bloopResponse = bloopChanged.add([](int i) { ... });
    // or
    decltype(bloopChanged)::Listener bloopResponse = ...
    
    // let bloopResponse go out of scope.
    // or re-assign it
    // or reset the shared_ptr to disconnect it
    bloopResponse.reset();
    

    I have made a gist for this too, with a more in-depth example: https://gist.github.com/johnb003/dbc4a69af8ea8f4771666ce2e383047d

提交回复
热议问题