0

GameObject objects are uncopyable. I want to move the object that gameObject is pointing to into the std::map<int,GameObject> gameObjects_ without invoking its copy constructor. This compiler errors with this code, indicating that I am trying to copy the object. What am I doing wrong?

void GameObjectManager::addObject(int id,GameObject* gameObject){
    gameObjects_.insert(std::make_pair(id,std::move(*gameObject)));
}
pighead10
  • 4,155
  • 10
  • 34
  • 52
  • Actually, your approach [works for me as is](http://ideone.com/8YMOz3). Must be a deficiency in your compiler. – Igor Tandetnik Jan 21 '14 at 22:58
  • 1
    [Related](http://stackoverflow.com/questions/14916474/stdmapinsert-using-non-copyable-objects-and-uniform-initialization). Maybe it's in they way you make your GameObject type non-copyable ? – François Moisan Jan 21 '14 at 23:20
  • François Moisan is correct - adding `GameObject(GameObject&&) {}` in the class means it compiles fine. Previously it was just inheriting from sf::NonCopyable. An explanation of this would be appreciated. – pighead10 Jan 23 '14 at 20:13

2 Answers2

2

The code you show is C++11 conforming. Here is a complete demo:

#include <map>

struct GameObject
{
    GameObject(GameObject&&) = default;
};

class GameObjectManager
{
    std::map<int, GameObject> gameObjects_;
public:

    void
    addObject(int id,GameObject* gameObject)
    {
        gameObjects_.insert(std::make_pair(id,std::move(*gameObject)));
    }
};

int
main()
{
}

which compiles using tip-of-trunk clang + libc++. Sorry, I do not have a VC10 workaround.

Update

Adding GameObject(GameObject&&) {} fixed the problem

Ah! If you want to move your objects, you must ensure that they have a move constructor (and usually move assignment operator too).

Here is a very brief tutorial on move semantics:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2027.html

It is somewhat dated, but it still correctly highlights the basics without a lot of reading.

In C++11, sometimes a move constructor and move assignment operator will be automatically generated for you. However VC10 does not implement compiler-supplied move members, so you don't need to worry about that aspect for now.

In your case (deriving from NonCopyable), move members can not be implicitly generated anyway. So you must supply your own. The link to the brief tutorial above describes how to do that, and what is actually going on. In particular, study the clone_ptr example.

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
  • Adding `GameObject(GameObject&&) {}` fixed the problem - an explanation would be appreciated. – pighead10 Jan 23 '14 at 20:13
  • 1
    I am now using Visual Studio 2013, but adding `GameObject(GameObject&&) = default;` results in error c2610: "is not a special member function which can be defaulted". – pighead10 Jan 23 '14 at 22:38
  • @pighead10: Sorry, looks like you'll have to wait for VS2014 for defaulted move members. In the meantime you can implement your move constructor manually as described at the tutorial link. – Howard Hinnant Jan 23 '14 at 22:52
0

Why not std::unqiue_ptr?

typedef std::unique_ptr<GameObject> GameObjectPtr;
typedef std::unordered_map<std::size_t, GameObjectPtr> GameObjectsMap;

then just reference the gameobject_t.

OneOfOne
  • 95,033
  • 20
  • 184
  • 185
  • I didn't want to do this because having a map of pointers causes an extra cache miss when iterating through them. Sure, it won't make any practical difference in any code I'll be writing, but I wanted to see how I would do it if I was writing performance critical code. – pighead10 Jan 21 '14 at 22:10