Showing posts with label STL. Show all posts
Showing posts with label STL. Show all posts

Monday, March 10, 2008

std::for_each with C-style arrays

Although std::for_each is most often used with the standard containers, it can also be used with C-style arrays. Take for example the following:
#include <algorithm>
#include <functional>
// ...
WriterTask writer[NumThreads];
std::for_each(writer, writer+NumThreads,
std::mem_fun_ref(&WriterTask::activate));
// ...
std::for_each(writer, writer+NumThreads,
std::mem_fun_ref(&WriterTask::join));
Or if you prefer:
std::for_each(&writer[0], &writer[NumThreads],
std::mem_fun_ref(&WriterTask::activate));
Compare the above with the explicit for loop:
for (int i = 0; i < NumThreads; ++i) {
writer[i].activate();
}
I'm not completely convinced that the std::for_each case is more readable. However, I liked it better than the for loop for some test cases I was writing. It collapsed a number of subsequent for loops down into one line statements making it clearer the intent of the test.

Monday, February 25, 2008

std::fill_n

Many of the tests I have been writing lately involve creating min/max/misc. values to send across our messaging system. It dawned on me today that the for loops I have been writing could be better expressed with std::fill_n. For example take the following loop:
std::vector<std::string> strSeq;
const int MAX_STRSEQ_SIZE = 31;
for (int i = 0; i < MAX_STRSEQ_SIZE; ++i)
strSeq.push_back("0123456789");
This can be better written using the standard template library:
std::vector<std::string> strSeq;
const int MAX_STRSEQ_SIZE = 31;
std::fill_n(std::back_inserter(strSeq), MAX_STRSEQ_SIZE,
"0123456789");
Although this isn't really any shorter than the original for loop, I believe it reads better.

Lets review std::fill_n():
template<typename ForwardIter, typename Size, typename T>
fill_n(ForwardIter begin, Size n, const T& value);
std::fill_n takes three arguments: ForwardIter, Size, and T. ForwardIter is designed to take an iterator pointing to where to begin filling. However, since std::fill_n assumes there is room in the container we use std::back_inserter() to adapt the assignment operator into a push_back on our container. Size is how many of T to assign and T is the value to assign.