简体   繁体   中英

Compiler error with unordered_map when used in template class

Since my example is somewhat complex, I have put a sample here that demonstrates the error (Code will be inlined below as well): http://coliru.stacked-crooked.com/a/a426995302bda656

#include <functional>
#include <unordered_map>
#include <memory>

enum class DeliveryMethodType
{
  POST_MASTER,
  BUBBLE,
};

class IDeliveryMethod
{
};

class BubbleDelivery : public IDeliveryMethod
{
};

template<typename Key, typename Interface>
class GenericFactory
{
public:

   using FactoryMethod = std::function<std::unique_ptr<Interface> ()>;

   static Key const& Register(Key const& key, FactoryMethod creator)
   {
      s_factoryMethods.insert({key, creator});
      return key;
   }

   static std::unique_ptr<Interface> Create(Key const& key)
   {
      std::unique_ptr<Interface> obj;

      auto it = s_factoryMethods.find(key);
      if (it != s_factoryMethods.end())
      {
         obj = it->second();
      }

      return obj;
   }

private:
   static std::unordered_map<Key, FactoryMethod> s_factoryMethods;
};

template<typename Key, typename Interface>
std::unordered_map<Key, typename GenericFactory<Key, Interface>::FactoryMethod>
GenericFactory<Key, Interface>::s_factoryMethods;

using DeliveryMethodFactory = GenericFactory<DeliveryMethodType, IDeliveryMethod>;

static auto key = DeliveryMethodFactory::Register(DeliveryMethodType::BUBBLE, []() {
      return std::unique_ptr<IDeliveryMethod>(new BubbleDelivery);
});

int main()
{
}

My design goal here is to create a generic static factory class. Each translation unit will (at static initialization time) invoke the Register() method for a specific specialization of GenericFactory for the desired key and factory method types.

I'm getting the following compiler error, which I'm not sure how to resolve.

error: implicit instantiation of undefined template 'std::hash<DeliveryMethodType>'

I imagine perhaps that my template trickery is failing here and I'm not doing something right. Can anyone help identify the issue here? Thanks.

The key type for an unordered container needs either a specialisation of std::hash defined for it, or a custom hash function provided to the container.

Since your container is in a template, with a generic key, it's tricky to provide a custom function; so provide a specialisation, for example:

namespace std {
    template <> struct hash<DeliveryMethodType> {
        size_t operator()(DeliveryMethodType x) const {
            return hash<int>()(static_cast<int>(x));
        }
    };
}

unordered_map has a default third parameter which is the hasher for the class contained in the container. Sometimes there is a default implementation of this, eg. for int or std::string - if not, you have to implement this.

对于unordered_map您必须通过提供std::hash<DeliveryMethodType> ob的实现,并通过提供自己的哈希函数作为unordered_map的构造函数参数,来为用户定义的键类型提供哈希函数。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM