Reputation: 1705
I have the class MyObject
. All instances of it should be owned by a MyObjectSet
, and it should not be possible to construct it anywhere else. Inside MyObjectSet
, I use a std::vector<MyObject>
to store all instances in.
The problem is, that for std::vector<MyObject>
to work, the move constructor of MyObject
has to be public (it is not enough to add std::vector<MyObject>
as a friend of MyObject
).
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 public, it would be possible to instantiate MyObject
from elsewhere.
void SomeUnrelatedFunc(MyObjectSet& set) {
MyObject m(std::move(set.GetMyObject(0))); // this shouldn't be possible
}
Is there any way to solve this problem?
It is possible to store pointers to MyObject
instances inside MyObjectSet
instead, but I'd like to avoid that, if possible.
Upvotes: 4
Views: 512
Reputation: 11567
You could create a custom allocator and pass it as the second parameter to your std::vector<>
. Make your custom allocator a friend of MyObject. Your custom allocator doesn't need to do anything special--the only purpose is to allocate MyObjects in the usual way (e.g. with new) while accessing the private constructor by virtue of being a friend.
Upvotes: 0
Reputation: 11567
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 construct your objects.
class MyObjectSet {
std::vector<MyObject> MyObjects;
public:
MyObject& GetMyObject(int some_param)
{
MyObjects.emplace_back( some_param );
return MyObjects.back();
}
};
emplace_back()
has the effect of calling the MyObject constructor, passing some_param as the int parameter to the constructor, and inserting the created object into the back of the list. The construct call is done from within std::allocator, so its friendship is required.
Upvotes: 2