开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜