I'm currently working on a big project and I need to use weak_ptr
instead of shared_ptr
.
Here is my problem.
I have a class named House with an attribute: vector<boost::shared_ptr<People>> my_people
.
I want to modify this data member to be vector<boost::weak_ptr<People>> my_people
.
My getter was
vector<boost::shared_ptr<People>>& getPeople() const
{
return my_people;
}
Normally, with a simple weak_ptr
I can return my_people.lock();
But I have a vector and I don't know how to do something like this:
vector<boost::shared_ptr<People>>& getPeople() const
{
for( vector<boost::weak_ptr<People>::iterator it = my_people.begin();
it != my_people.end();
++it)
{
(*it).lock();
}
return my_people;
}
In other words, I want to return my vector of weak_ptr
but as a vector of shared_ptr
. Is it possible? Or do I have to return a vector of weak_ptr
and use lock()
everywhere I use them?
Your function is a reasonable start:
vector<boost::shared_ptr<People>>& getPeople() const
{
for( vector<boost::weak_ptr<People>::iterator it = my_people.begin();
it != my_people.end();
++it)
{
(*it).lock();
}
return my_people;
}
But calling (*it).lock()
just creates a shared_ptr
and throws it away, it doesn't change the type of the vector elements, and you can't return the vector as a different type.
You need to create a vector of the right type, fill it with the shared_ptr objects, and return it:
vector<boost::shared_ptr<People>> getPeople() const
{
vector<boost::shared_ptr<People>> people(my_people.size());
std::transform(my_people.begin(), my_people.end(), people.begin(),
boost::bind(&boost::weak_ptr<People>::lock, _1));
return people;
}
This iterates over each element of my_people
, calls lock()
on it, and assigns the result to the corresponding element of people
.
If you know that my_people
never contains expired pointers it's even easier:
vector<boost::shared_ptr<People>> getPeople() const
{
vector<boost::shared_ptr<People>> people(my_people.begin(), my_people.end());
return people;
}
This fills the people
vector by constructing each shared_ptr
element from a weak_ptr
element. The difference is that this version will throw an exception if a weak_ptr
has expired because the shared_ptr
constructor throws if passed an expired weak_ptr
. The version usingtransform
will put an empty shared_ptr
in the vector if an expired weak_ptr is transformed.
You could use std::transform
std::vector<std::shared_ptr<People>> temp;
sharedTargetList.resize(my_people.size());
//transform into a shared_ptr vector
std::transform(my_people.begin(),
my_people.end(),
temp.begin(),
[](std::weak_ptr<People> weakPtr){ return weakPtr.lock(); }
);
What about:
vector<boost::shared_ptr<People>> getPeople() const
{
vector<boost::shared_ptr<People>> res;
for( vector<boost::weak_ptr<People>::iterator it = my_people.begin();
it != my_people.end(); ++it)
res.push_back(it->lock());
return res;
}
Also, you can filter out the null pointers, if you want.
Of course, you cannot return a reference to a local variable so you have to return a copy. You may want to do instead:
void getPeople(vector<boost::shared_ptr<People>> &res) const
{
for( vector<boost::weak_ptr<People>::iterator it = my_people.begin();
it != my_people.end(); ++it)
res.push_back(it->lock());
}
to avoid copying the return vector.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With