C++ unordered_multimap вставить хеш

Я схожу с ума здесь. У меня есть поиск в Google, чтобы найти 1 единственный достойный пример, где люди используют unordered_map вместе с классом enum и хэш-функцией без какой-либо удачи. Те, кого мне удается найти, всегда заканчивают тем, что говорят "используйте карту вместо"

Я пытаюсь сделать следующее:

Enum class facing это направление, на которое смотрит мой спрайт.

Enum class Action это действие, которое делает мой спрайт.

Animation это класс, который содержит различные анимации, которые я буду называть позже.

Контейнер должен выглядеть так:

карта

В качестве ключа может быть более 1 FACING на карте, и в паре может быть более одного ACTION.

Пример:

map<LEFT, pair<ATTACK, attackAnimation>
map<LEFT, pair<IDLE, idleAnimation>
map<LEFTUP, pair<IDLE, idleAnimation>

Это упрощенное все

#include <iostream>
#include <unordered_map>
#include <string>
#include <memory>

template <typename T>
struct Hash
{
    typedef typename std::underlying_type<T>::type underlyingType;
    typedef typename std::hash<underlyingType>::result_type resultType;
    resultType operator()(const T& arg) const
    {
        std::hash<underlyingType> hasher;
        return hasher(static_cast<underlyingType>(arg));
    }
};

class Animation
{
private:
    std::string str;

public:
    Animation(std::string _string)
    {
        this->str = _string;
    }

    std::string& GetString()
    {
        return this->str;
    }
};

class Bullshit
{
public:
    enum class Action
    {
        Attack,
        Move
    };

    enum class Facing
    {
        Right,
        Up,
        Left
    };

    Bullshit()
    {

    }

    std::unordered_multimap<Bullshit::Facing, std::pair<Bullshit::Action, std::unique_ptr<Animation>>,Hash<Bullshit::Facing>>& GetlistAnimation()
    {
        return this->listAnimation;
    }

private:
    std::unordered_multimap<Bullshit::Facing, std::pair<Bullshit::Action, std::unique_ptr<Animation>>,Hash<Bullshit::Facing>> listAnimation;
};


int main()
{
    Bullshit bull;
    auto myList = bull.GetlistAnimation();

    std::unique_ptr<Animation> anim(new Animation("test"));
    myList.insert(std::make_pair(Bullshit::Facing::Up, std::make_pair(Bullshit::Action::Attack, std::move(anim))));

    std::cin.get();
    return 0;
}

Код ошибки:

error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
1>          with
1>          [
1>              _Ty=Animation
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\memory(1447) : see declaration of 'std::unique_ptr<_Ty>::unique_ptr'
1>          with
1>          [
1>              _Ty=Animation
1>          ]
1>          This diagnostic occurred in the compiler generated function 'std::pair<_Ty1,_Ty2>::pair(const std::pair<_Ty1,_Ty2> &)'
1>          with
1>          [
1>              _Ty1=Bullshit::Action,
1>              _Ty2=std::unique_ptr<Animation>
1>          ]

2 ответа

Решение

Вот

auto myList = bull.GetlistAnimation();

тип выведен для myList является std::unordered_map<.....>то есть это не ссылка. И копия не может быть создана, потому что карта содержит unique_ptrs. Что ты имел в виду

auto& myList = bull.GetlistAnimation();

или в C++14,

decltype(auto) myList = bull.GetlistAnimation();

Проблема не имеет ничего общего с unordered_map или хэш-функции. Это std::unique_ptr, который нельзя скопировать, а ваш GetlistAnimation пытается скопировать его (косвенно).

Как правильно это исправить, зависит от того, чего вы хотите добиться.

Быстрое решение будет использовать std::shared_ptr вместо:

    std::unordered_map<Bullshit::Facing, std::pair<Bullshit::Action, std::shared_ptr<Animation>>,Hash<Bullshit::Facing>>& GetlistAnimation()
    {
        return this->listAnimation;
    }

private:
    std::unordered_map<Bullshit::Facing, std::pair<Bullshit::Action, std::shared_ptr<Animation>>,Hash<Bullshit::Facing>> listAnimation;

[...]

std::shared_ptr<Animation> anim(new Animation("test"));
myList.insert(std::make_pair(Bullshit::Facing::Up, std::make_pair(Bullshit::Action::Attack, anim)));

(Кстати, вы должны использовать std::make_shared а также std::make_unique.)


Исправление, которое может быть быстрым и правильным (опять же, в зависимости от того, чего вы хотите достичь), состоит в том, чтобы полностью избавиться от логики указателя и просто использовать Animation непосредственно:

    std::unordered_map<Bullshit::Facing, std::pair<Bullshit::Action, Animation>,Hash<Bullshit::Facing>>& GetlistAnimation()
    {
        return this->listAnimation;
    }

private:
    std::unordered_map<Bullshit::Facing, std::pair<Bullshit::Action, Animation>,Hash<Bullshit::Facing>> listAnimation;

[...]

Animation anim("test");
myList.insert(std::make_pair(Bullshit::Facing::Up, std::make_pair(Bullshit::Action::Attack, anim)));
Другие вопросы по тегам