Shortest conversion from vector to vector of pointer
Is there any shortcut to convert from std::vector<T>
to std::vector<T*>
or std::vector<T&>
?
Essentially I want to replace:
std::vector<T> source;
std::vector<T*> target;
for(auto it = source.begin(); it != source.end(); it++)
{
target.push_back(&(*it));
}
with a single line.
To provide some context: I have one set of functions which do their computation on a std::vector<Polygon>
and some which require std::vector<Polygo开发者_开发问答n*>
. So I need to convert back and forth a couple of times, because the interface of these functions is not supposed to change.
Although what you describe sounds strange (without context), using std::transform
you could do the actual copying/transformation in one line of code :
transform(source.begin(), source.end(), target.begin(), getPointer);
given that target
has sufficient room for all data (can be achieved with std::vector::resize
eg.), and given this unary operator :
template<typename T> T* getPointer(T& t) { return &t; }
If you have got c++0x the following code does the trick (c++0x needed for lambdas):
template <typename T>
std::vector<T*> convertFrom(std::vector<T>& source)
{
std::vector<T*> target(source.size());
std::transform(source.begin(), source.end(), target.begin(), [](T& t) { return &t; });
return target;
}
One side note: Make sure the source vector is not cleaned up before the last usage of the target vector as it is the owner of the actual objects. The target vector only contains the pointers.
Another idea to my previous answer, is to use boost iterators.
Since it's sufficiently different, I thought I'd post it as a new response :
First using the boost::transform_iterator
:
template<typename T> T* getPointer(T& t) { return &t; }
boost::transform_iterator<T* (*)(T&), std::vector<T>::iterator> begin(source.begin(), getPointer), end(source.end(), getPointer);
std::vector<T*> target(begin, end);
Or to construct the source
vector from the target
vector (if that direction also works for you), you can use the boost::indirect_iterator
:
boost::indirect_iterator<std::vector<T*>::iterator> begin(target.begin()), end(target.end());
std::vector<T> source(begin, end);
It might not be as pretty, but it's effective.
精彩评论