Initialize a Stl vector of type T * from an array of type T

if I have an array, for example:

struct S {... }; S m_aArr[256]; 

and I want to use it to build a vector, for example:

 std::vector<S*> m_vecS; 

Is there a way to do this, rather than scrolling & casting back &m_aArr[i] ? I understand that I can not use the traditional method of using std::begin and std::end in an array, since the vector is one of the pointers and the original array is one of the objects, so we can not just go through the memory block.

+4
source share
3 answers

You can use the standard library to iterate and return for you:

 std::transform(std::begin(m_aArr), std::end(m_aArr), std::back_inserter(m_vecS), std::addressof<S>); 

This converts each of the elements to m_aArr by applying the std::addressof<S> function to them. Each of the converted elements is then push_back ed to m_vecS using the std::back_inserter .

To do this before C ++ 11, you will not have access to std::begin , std::end or std::addressof , so it will look something like this:

 std::transform(m_aArr, m_aArr + 256, std::back_inserter(m_vecS), boost::addressof<S>); 

It uses boost::addressof .

+12
source

You can let std::transform execute a loop:

 transform(std::begin(a), std::end(a), std::back_inserter(v), [] (S& s) { return &s; }); 

Note that you do not need to fully qualify the name std::transform , because the function name will be found by ADL .

This is a complete program to test its behavior:

 #include <iostream> #include <vector> #include <algorithm> // <== Required for std::transform #include <iterator> // <== Required for std::back_inserter, std::begin, std::end struct S { S() : i(0) { } S(int i_) : i(i_) { } int i; }; int main() { S a[256] = { 42 }; // Copy-initializes first element from 42, // default-constructs all other elements std::vector<S*> v; transform(std::begin(a), std::end(a), std::back_inserter(v), [] (S& s) { return &s; }); std::cout << v.size() << std::endl; // Prints 256 std::cout << v[0]->i << std::endl; // Prints 42 std::cout << v[1]->i << std::endl; // Prints 0 } 

And here is a living example .

+5
source

A solution using std::generate_n() that performs a single selection of std::vector instead of potentially multiple through std::vector::push_back() :

 #include <iostream> #include <vector> #include <algorithm> #include <iterator> int main() { struct S {}; S a[128]; S* ap = a; std::vector<S*> v(sizeof(a)/sizeof(a[0])); std::generate_n(std::begin(v), v.size(), [&]() { return ap++; }); for (size_t i = 0; i < v.size(); i++) { if (&a[i] != v[i]) // Ensure same address at each element. { std::cerr << "Error\n"; break; } } return 0; } 

Watch online at http://ideone.com/73nKST .

+1
source

All Articles