Using std :: unique_ptr inside map as key

I am using Visual Studio 2012. I have a map that looks like this:

std::map<std::string,std::map<std::unique_ptr<sf::Sound>,std::unique_ptr<sf::SoundBuffer>>> listSoundContainer;

      

I am trying to insert data like this:

std::unique_ptr<sf::SoundBuffer> soundBuffer(new sf::SoundBuffer());
if (soundBuffer->loadFromFile("assets/sound/" + _fileName) != false)
{
    std::unique_ptr<sf::Sound> sound(new sf::Sound(*soundBuffer));
    typedef std::map<std::unique_ptr<sf::Sound>, std::unique_ptr<sf::SoundBuffer>> innerMap;
    listSoundContainer[_fileName].insert(innerMap::value_type(std::move(sound), std::move(soundBuffer)));               
}

      

and im getting the following error at compile time:

microsoft visual studio 11.0 \ vc \ include \ utility (182): error C2248: 'std :: unique_ptr <_Ty> :: unique_ptr': cannot access a private member declared in class 'std :: unique_ptr <_Ty>' > c 1>
[1> _Ty = sf :: Sound 1>] 1> c: \ program files (x86) \ microsoft visual studio 11.0 \ vc \ include \ memory (1447): see declaration 'std :: unique_ptr < _Ty> :: unique_ptr '1> c 1> [1> _Ty = sf :: Sound 1>] 1> c: \ program files (x86) \ microsoft visual studio 11.0 \ vc \ include \ xmemory0 (617): see reference to the instance of the function template "Std :: pair <_Ty1, _Ty2> :: pair (std :: pair <_Ty1, _Ty2> & &, void **) 'compiled 1> with 1> [1>
_Ty1 = const std: : unique_ptr, 1> _Ty2 = std :: unique_ptr, 1>_Kty = std :: unique_ptr, 1> _Ty = std :: unique_ptr 1>]

I also tried inserting data using make_pair with the same problem. What am I missing? I have been trying to fix this issue for 2 hours and cannot get around it.

I can solve this problem by NOT using smart pointers:

sf::SoundBuffer* soundbuffer = new sf::SoundBuffer();
soundbuffer->loadFromFile(_file);
sf::Sound* sound = new sf::Sound(*soundbuffer);
typedef std::map<sf::SoundBuffer*, sf::Sound*> mapType;
listSound[_file].insert(mapType::value_type(soundbuffer, sound));

      

+3


source to share


2 answers


Look at the template definition for std::map

:

template<
    class Key,
    class T,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<std::pair<const Key, T> >
> class map;

      

And now let's see how you are trying to create it:

std::map<
    std::string, 
    std::map<
        std::unique_ptr<sf::Sound>, 
        std::unique_ptr<sf::SoundBuffer>
    >
> 
listSoundContainer

      



The problem is that a std::unique_ptr<sf::Sound>

cannot act like a key.

What you are trying to do is make some kind of list std::pair<std::unique_ptr<sf::Sound>, std::unique_ptr<sf::SoundBuffer>>

I would suggest using this instead:

std::map<
    std::string, 
    std::list<
        std::pair<
            std::unique_ptr<sf::Sound>, 
            std::unique_ptr<sf::SoundBuffer>
        >
    >
> 
listSoundContainer

      

+1


source


Smart pointers should not be used in conjunction with STL containers.

The background is that smart pointers don't behave as expected by STL containers. For example, the STL expects the original objects of a copy operation to remain unchanged. This does not apply to smart pointers. This can lead to the strange consequences that you are experiencing ...



EDIT: My answer was not entirely correct. Since C ++ 11 it is possible to use smart pointers e.g. unique_ptr, with STL containers.

0


source







All Articles