Saving a vector of non-constructive objects

I have a class MyObject . All instances of it must belong to MyObjectSet , and it would not be possible to build it anywhere else. Inside MyObjectSet I use std::vector<MyObject> to store all instances.

The problem is that for std::vector<MyObject> to work, the std::vector<MyObject> move constructor must be publicly available (adding std::vector<MyObject> as a friend of MyObject not enough).

 class MyObject { MyObject(int n); friend class MyObjectSet; public: MyObject(MyObject&&) = default; // without this, it doesn't compile }; class MyObjectSet { std::vector<MyObject> MyObjects; public: MyObject& GetMyObject(int some_param); }; 

But if I make it publicly available, I could create an instance of MyObject from another place.

 void SomeUnrelatedFunc(MyObjectSet& set) { MyObject m(std::move(set.GetMyObject(0))); // this shouldn't be possible } 

Is there any way to solve this problem?

You can save pointers to MyObject instances inside MyObjectSet instead, but I would like to avoid this if possible.

+4
source share
3 answers

You need to declare std::allocator<MyObject> as a friend:

 class MyObject { MyObject(int n); friend class MyObjectSet; friend std::allocator<MyObject>; }; 

Then use vector::emplace_back() to actually create your objects.

 class MyObjectSet { std::vector<MyObject> MyObjects; public: MyObject& GetMyObject(int some_param) { MyObjects.emplace_back( some_param ); return MyObjects.back(); } }; 

emplace_back() makes sense to call the constructor MyObject, passing some_param as an int parameter to the constructor and inserting the created object at the end of the list. The construction call is made from std :: allocator, so its friendship is required.

+2
source

The accepted answer to this post describes a workaround for a similar problem (using a regular constructor rather than a move constructor). Perhaps you can take some ideas from there?

0
source

You can create your own dispenser and pass it as your second parameter to your std::vector<> . Make your custom allocator a friend of MyObject. Your custom distributor should not do anything special - the only purpose is to highlight MyObjects in the usual way (for example, with a new one) when accessing a private constructor because you are a friend.

0
source

All Articles