James May
James May

Reputation: 1537

Nested unordered_map has no member named ‘emplace’

I trying to fix pretty hard program to me I got from gamedev book. I think it's crashed because an author used Windows and I use Linux (g++). In short I have couple of classes to perform Application State's logic, and I have map of maps to hold states with its callbacks:

enum class StateType {
    Intro = 1, MainMenu, Game, Paused, GameOver, Credits
};

using Bindings  = std::unordered_map<std::string, Binding*>;
using CallbackContainer = std::unordered_map<std::string, std::function<void(EventDetails*)>>;
using Callbacks = std::unordered_map<StateType, CallbackContainer>;

class EventManager {
public:
...
    template<class T>
    bool AddCallback(StateType l_state, const std::string& l_name, 
        void(T::*l_func)(EventDetails*), T* l_instance) {
        auto itr = m_callbacks.emplace(l_state, CallbackContainer()).first;
        auto temp = std::bind(l_func, l_instance, std::placeholders::_1);
        return itr->second.emplace(l_name, temp).second;
    }

private:
    Callbacks m_callbacks;

I'm not sure what parts of my code to include here. Anyway I get a terrible stack trace:

/usr/include/c++/5/bits/hashtable_policy.h: In instantiation of ‘struct std::__detail::__is_noexcept_hash<StateType, std::hash<StateType> >’:
/usr/include/c++/5/type_traits:137:12:   required from ‘struct std::__and_<std::__is_fast_hash<std::hash<StateType> >, std::__detail::__is_noexcept_hash<StateType, std::hash<StateType> > >’
/usr/include/c++/5/type_traits:148:38:   required from ‘struct std::__not_<std::__and_<std::__is_fast_hash<std::hash<StateType> >, std::__detail::__is_noexcept_hash<StateType, std::hash<StateType> > > >’
/usr/include/c++/5/bits/unordered_map.h:100:66:   required from ‘class std::unordered_map<StateType, std::function<BaseState*()> >’
/home/xxx/Projects/mushrooom/BaseState.h:48:28:   required from here
/usr/include/c++/5/bits/hashtable_policy.h:85:34: error: no match for call to ‘(const std::hash<StateType>) (const StateType&)’
  noexcept(declval<const _Hash&>()(declval<const _Key&>()))>
...
/usr/include/c++/5/bits/unordered_map.h:649:7: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<StateType> >, std::__detail::__is_noexcept_hash<StateType, std::hash<StateType> > > >’
       equal_range(const key_type& __x) const
...
/home/xxx/Projects/mushrooom/EventManager.h: In member function ‘bool EventManager::AddCallback(StateType, const string&, void (T::*)(EventDetails*), T*)’:
/home/xxx/Projects/mushrooom/EventManager.h:93:32: error: ‘using Callbacks = class std::unordered_map<StateType, std::unordered_map<std::basic_string<char>, std::function<void(EventDetails*)> > > {aka class std::unordered_map<StateType, std::unordered_map<std::basic_string<char>, std::function<void(EventDetails*)> > >}’ has no member named ‘emplace’
         auto itr = m_callbacks.emplace(l_state, CallbackContainer()).first;

Seems like Callbacks has no member emplace, but it's std::unordered_map and it has such method.

g++-5, linux

Upvotes: 1

Views: 3292

Answers (1)

Aconcagua
Aconcagua

Reputation: 25516

It has nothing to do with emplace - it is the missing hash function!

You are using an std::unordered_map, which is in other words a hash map. If you want to use an object as a key, this object must provide a function by which a hash value can be calculated.

You now have two options:

  1. provide a template specialisation of std::hash for your class or pass an own class as third (hasher) template parameter to std::unordered_map
  2. use std::map instead - this is a tree-map not requiring a hash function.

Upvotes: 3

Related Questions