Я пытаюсь реализовать std::unordered_map с std::string в качестве ключа и std::unique_ptr в качестве значения. Однако, когда я пытаюсь скомпилировать, я получаю сообщение об ошибке:
error C2338: The C++ Standard doesn't provide a hash for this type.
Просматривая разные вопросы, я знаю, что С++ 11 действительно включает std::hash ‹ std::string >, и я не вижу причин, по которым эта ошибка может быть выдана. Я попытался реализовать свою собственную хеш-функцию, подобную той, которую видели здесь, но все равно выдает ту же ошибку. Я также пытался использовать __declspec(dllexport)
и сделать конструктор копирования и оператор присваивания для содержащего класса закрытым, как это предлагается в некоторых потоках, чтобы заставить работать unique_ptr, но безрезультатно.
Вот код класса-нарушителя:
#ifndef __TEXTURE_MAP_H__
#define __TEXTURE_MAP_H__
#include <unordered_map>
#include <vector>
#include <memory>
#include <string>
//__declspec for std::unique_ptr compat.
class /*__declspec(dllexport)*/ TextureMap : virtual public IconRegister
{
private:
uint32 _textureId;
std::unordered_map<const std::string, std::unique_ptr<AtlasTexture> > _registeredIcons;
std::unordered_map<const char*, AtlasTexture*> _uploadedIcons;
std::vector<AtlasTexture*> _animatedIcons;
public:
TextureMap();
~TextureMap();
uint32 getTextureId();
void loadTextureAtlas();
/* override */ IIcon& registerIcon(const char*);
void registerIcons();
private:
TextureMap(const TextureMap& other) { }
TextureMap& operator= (const TextureMap& other) { return *this; };
};
#endif
Я не могу найти причину, по которой это не должно работать, и я пробовал почти все другие решения, которые мог найти, когда искал проблему.
Я использую MSVC 2012.
Любая помощь приветствуется. Спасибо.
EDIT: добавление класса AtlasTexture: header и реализация
РЕДАКТИРОВАТЬ: Моя реализация перемещения и задания перемещения: здесь.
_registeredIcons
не должен бытьconst
— просто старый добрыйstd::string
(hash
предназначен дляstring
, а неconst string
). Кроме того,std::hash(const char*)
будет хэшировать адрес указателя, а не текст, на который он указывает.... это действительно то, что вы хотите? - person Tony Delroy   schedule 13.02.2014unique_ptr<>
не является допустимым типом для сопоставления... согласно 23.2.5.10 key_type и mapped_type иногда требуется, чтобы они были CopyAssignable -unique_ptr
не является CopyAssignable. Вы можете использоватьshared_ptr
. - person Tony Delroy   schedule 13.02.2014unordered_map<string, int>
. Удалите все другие смешанные факторы (const
,unique_ptr
). - person juanchopanza   schedule 13.02.2014mapped_type
было CopyAssignable, но не все. Определенно работает в этом тривиальном случае использования. - person Praetorian   schedule 13.02.2014unique_ptr
в качествеvalue_type
. - person Casey   schedule 13.02.2014const
доступ к своим членам. Я думаю, что у VALOD9 есть правильный ответ ниже. sm81095: Попробуйте реализовать конструктор перемещения и оператор присваивания перемещения дляAtlasTexture
. - person Praetorian   schedule 13.02.2014std::unordered_map<std::string, std::unique_ptr<int>>
кажется пригодным для использования в VS2013.. - person Casey   schedule 13.02.2014unique_ptr
в карту. Можете ли вы показать нам эту часть кода? (Я полагаю,registerIcon
/registerIcons
?) - person Casey   schedule 13.02.2014_registeredIcons.insert(std::move(std::make_pair(path, std::unique_ptr<AtlasTexture>(obj))));
, где path — этоconst char*
, аobj
— это указатель AtlasTexture, созданный всего несколькими строками выше. - person sm81095   schedule 13.02.2014make_pair
-std::pair<const char*,std::unique_ptr<AtlasTexture>>
- в value_type картыstd::pair<const std::string,std::unique_ptr<AtlasTexture>>
. Я предлагаю использоватьemplace
вместоinsert
. (Кроме того, бессмысленноstd::move
результат функции, которая уже является rvalue). - person Casey   schedule 13.02.2014registerIcons()
. - person sm81095   schedule 13.02.2014emplace
. Сложный способ — использоватьinsert(std::pair<const std::string,std::unique_ptr<AtlasTexture>>(path,std::unique_ptr<AtlasTexture>(obj)))
. В частности,_registeredIcons.emplace(path, std::unique_ptr<AtlasTexture>(obj));
- person Casey   schedule 13.02.2014This diagnostic occurred in the compiler generated function 'std::pair<_Ty1,_Ty2>::pair(const std::pair<_Ty1,_Ty2> &)'
. Может лиfor (auto pair : _registeredIcons)
быть причиной этого? - person sm81095   schedule 13.02.2014auto
является копией; вы можете указать либоauto&
, либоauto const&
в зависимости от того, может ли ссылка бытьconst
или нет. - person Matthieu M.   schedule 13.02.2014.insert()
на.emplace
и заменыauto
наauto&
. Спасибо всем, кто помог. - person sm81095   schedule 13.02.2014