Find and remove a std :: function object from a vector map

I'm currently trying to implement a messaging system for my game engine. It uses the form callback functions:

typedef std::function<void(const Message &)> Callback;

It maintains a list of messages:

mutable std::vector<std::unique_ptr<Message>> messageList;

And signature feedback dictionary:

mutable std::map<std::string, std::vector<Callback>> callbackDictionary;

which is used to call all callback bindings to a particular type of message. When the callback function is called, a corresponding message is sent. So far so good.

For a better understanding, here is a subscription method that allows the user to add a function method that is called for each message of a signed type.

void Messenger::Subscribe(Message::Type type, Callback callbackFunction) 
const
{
    callbackDictionary[type].push_back(callbackFunction);
}

And here is an example of how it was used (by class of class with the ability to click)

messageBus.Subscribe("Message/Click", [this](const Message & message) {this->OnClick(static_cast<const ClickMessage &>(message)); });

Now my problem is:

, / . , . - :

void Messenger::UnSubscribe(Callback callbackFunction)
{
    for (auto & pair : callbackDictionary)
    {
        auto & functionList = pair.second;
        for (auto function : functionList)
        {
            if (function == callbackFunction)
                functionList.erase(std::remove(functionList.begin(), functionList.end(), function), functionList.end());
            // I am aware of issues that may appear from looping deleting while looping
        }
    }
}

(==) undefined . . , . - , , - . , .

+4
2

std:: function . tr1::function N1667:

operator== tr1::function ++, , T Comparable

, std::function<void(const Message &)> . , ( , , std::function ).

1:

std:: function value map vector.

std::map<std::string, std::map<std::string, Callback>> callbackDictionary;
. . .
void Messenger::Subscribe(Message::Type type, const std::string& cbID, Callback cb);

void Messenger::UnSubscribe(const std::string& cbID);

2:

weak_ptr, .

std::map<std::string, std::vector<std::weak_ptr<Callback>> callbackDictionary;
. . .
void Messenger::Subscribe(Message::Type type, std::shared_ptr<Callback> cb);

UnSubscribe ! , weak_ptr nullptr. , shared_ptr.

+1

std::function invokables, . , == , lambdas == compariable.

typeid invokable, false, , , == , , , ==.

" ", " ". , :

using std::shared_ptr<void> token;

template<class...Message>
struct broadcaster {
  using listener = std::function<void(Message...)>;
  using splistener = std::shared_ptr<listener>;
  using wplistener = std::weak_ptr<listener>;

  token listen( listener f ) {
    auto sf = std::make_shared<listener>(std::move(f));
    listeners.push_back(sf); // as weak ptr
    return sf; // as token
  }
  std::size_t operator()( Message... message ) const {
    // remove stale targets:
    targets.erase( std::remove_if( begin(targets), end(targets),
      [](auto&& ptr) { return !ptr.lock(); }
    ), end(targets) );
    auto tmp = targets; // copy, for reentrancy
    for (auto wf : tmp) {
      if(auto sf = wf.lock()) {
        sf( message... );
      }
    }
  }
private:
  mutable std::vector<wplistener> targets;
};

, . , , . std::vector<token> .

, , .

, , /, moreso. , / (, ), . listen .


"no lambdas ". , ==, bob - .

state( some_state... )
([](some_state&&...){
  return [&](some_args...){
  /* code */
});

, , , , , == .

template<class F, class...Args>
struct bound_state {
  std::tuple<Args...> state;
  F f;
  friend bool operator==( bound_state const& lhs, bound_state const& rhs ) {
    return lhs.state==rhs.state;
  }
  template<class...Ts>
  decltype(auto) operator()(Ts&&...ts){
    return std::apply(f, state)( std::forward<Ts>(ts)... );
  }
};
template<class...Args>
auto state( Args&&... args ) {
  auto tup = std::make_tuple( std::forward<Args>(args)... );
  return [tup=std::move(tup)](auto&& f) {
    return bound_state<std::decay_t<decltype(f)>, std::decay_t<Args>...>{
      tup, decltype(f)(f)
    };
  };
}

somesuch.

std::function. == ( , ) ( std::function s).

==, , typeid, == .

template<class Sig>
struct func_with_equal : std::function<Sig> {
  using Base = std::function<Sig>;
  using Base::operator();
  using equality = bool( func_with_equal const&, func_with_equal const& );      
  equality* pequal = nullptr;

  template<class F>
  static equality* erase_equality() {
    return [](func_with_equal const& lhs, func_with_equal const&rhs)->bool {
      assert( lhs.target_type() == rhs.target_type() );
      assert( lhs.target_type() == typeid(F) );
      return *lhs.target<F>() == *rhs.target<F>();
    };
  }
  // on construction, store `erase_equality<F>()` into `pequal`.

  friend bool operator==( func_with_equal const& lhs, func_with_equal const& rhs ) {
    if (!lhs && !rhs) return true;
    if (!lhs || !rhs) return false;
    if (lhs.target_type() != rhs.target_type()) return false;
    return lhs.pequal( lhs, rhs );
  }
};

, , . , .

+1

Source: https://habr.com/ru/post/1689160/


All Articles