vendredi 27 avril 2018

Mapping objects as key with unordered_map

I have a simple Observable class, implementing the observer pattern. This class maps a template type Event to registered observers. This is all fine, though instead of std::map I'd like to use std::unordered_map for performance reasons.

If I change the member variable below to use an unordered_map I get a rather generic error:

std::map<Event, std::vector<std::function<void()>>> _observers;

Static_assert failed "the specified hash does not meet the Hash requirements"

My expectation was that std::map and std::unordered_map should be interchangeable. What are the hashing requirements to use unordered_map in this case, and why is it different?

This is my code:

#include <functional>
#include <unordered_map>
#include <map>
#include <vector>
#include <utility>

template <typename Event>
class Observable
{
public:
    Observable()=default;

    template <typename Observer>
    void registerObserver(const Event &event, Observer &&observer)
    {
        _observers[event].push_back(std::forward<Observer>(observer));
    }

    template <typename Observer>
    void registerObserver(Event &&event, Observer &&observer)
    {
        _observers[std::move(event)].push_back(std::forward<Observer>(observer));
    }

    void notify(const Event &event) const
    {
        for (const auto& obs : _observers.at(event)) obs();
    }

    /* disallow copying */
    Observable(const Observable&)=delete;
    Observable& operator=(const Observable&)=delete;

private:
    std::map<Event, std::vector<std::function<void()>>> _observers;
};

Aucun commentaire:

Enregistrer un commentaire