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

前端 未结 5 1352
囚心锁ツ
囚心锁ツ 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 04:52

    I think that bind makes it easier to create slots (cfr. the 'preferred' syntax vs. the 'portable' syntax - that's all going away). The observer management, however, is not becoming less complex.

    But as @R. Martinho Fernandes mentions: an std::vector > is now easily created without the hassle for an (artificial) 'pure virtual' interface class.


    Upon request: an idea on connection management - probably full of bugs, but you'll get the idea:

    // note that the Func parameter is something
    // like std::function< void(int,int) > or whatever, greatly simplified
    // by the C++11 standard
    template
    struct signal {
      typedef int Key; // 
      Key nextKey;
      std::map connections;
    
      // note that connection management is the same in C++03 or C++11
      // (until a better idea arises)
      template
      Key connect( FuncLike f ) {
         Key k=nextKey++;
         connections[k]=f;
         return k;
      }
    
      void disconnect(Key k){
         connections.erase(k);
      }
    
      // note: variadic template syntax to be reviewed 
      // (not the main focus of this post)
      template
      typename Func::return_value call(Args... args){
         // supposing no subcription changes within call:
         for(auto &connection: connections){
            (*connection.second)(std::forward(...args));
         }
      }
    };
    

    Usage:

    signal> xychanged;
    
    void dump(int x, int y) { cout << x << ", " << y << endl; }
    
    struct XY { int x, y; } xy;
    
    auto dumpkey=xychanged.connect(dump);
    auto lambdakey=xychanged.connect([&xy](int x, int y){ xy.x=x; xy.y=y; });
    
    xychanged.call(1,2);
    

提交回复
热议问题