views:

580

answers:

3

I have a vector of pointers that are not owned by the container. How do I use algorithms on the targets of the pointers. I tried to use boost's ptr_vector, but it tries to delete the pointers when it goes out of scope.

Here is some code that needs to work:

vector<int*> myValues;
// ... myValues is populated
bool consistent = count(myValues.begin(), myValues.end(), myValues.front()) == myValues.size();
auto v = consistent ? myValues.front() : accumulate(myValues.begin(), myValues.end(), 0) / myValues.size();
fill(myValues.begin(), myValues.end(), v);
// etc.

I realize that for loops would work, but this happens in a bunch of places, so some kind of unary adapter? I wasn't able to find one. Thanks in advance!

A: 

You can look at boost::shared_ptr<> - a smart pointer with reference counting. It will not delete the pointer after it goes out of scope.

Eugene
the problem is that the pointers are to member variable in other objects. I could make those into shared_ptr too, but that might not be the most efficient way to do this.
Neil G
+13  A: 

You could use Boost Indirect Iterator. When dereferenced (with operator*() ), it applies an extra dereference, so you end up with the value pointed by the pointer referenced by the iterator. For more information, you can also see this question about a dereference iterator.

Here's a simple example:

std::vector<int*> vec;

vec.push_back(new int(1));
vec.push_back(new int(2));

std::copy(boost::make_indirect_iterator(vec.begin()),
          boost::make_indirect_iterator(vec.end()),
          std::ostream_iterator<int>(std::cout, " "));     // Prints 1 2
Luc Touraille
This is exactly what I was looking for, thanks!
Neil G
oh, nice, that was your question -- way to pass on the knowledge ;)
Neil G
+3  A: 
bool consistent = count_if(myValues.begin(), myValues.end(), 
   bind2nd(ptr_fun(compare_ptr), *myValues.front())) == myValues.size();

int v = consistent ? *myValues.front() : accumulate(
   myValues.begin(), myValues.end(), 0, sum_int_ptr) / myValues.size();

for_each(myValues.begin(), myValues.end(), bind1st(ptr_fun(assign_ptr),v));

Fill can't take assign function (so that it would dereference pointers). Therefore for_each() was used. For optimization it would be wise to add if(!consistent) before running for_each(). Functions used in above STL one liners:

int sum_int_ptr(int total, int * a) { return total + *a; }    
void assign_ptr(int v, int *ptr) { *ptr = v; }    
bool compare_ptr(int* a, int pattern) { return *a == pattern; }
Thanks, I learned a lot from your reply. I will probably go with the boost indirect iterators here, but it's nice to know how how to use bind1st, bind2nd, and so on.
Neil G
yeah STL is quite powerful, it is worth knowing all these one-liners like accumulate, etc.
PS.: Worth reading: http://www.keithschwarz.com/cs106l/fall2007/handouts/200_STL_Functional_Library.pdf