Compare
to
size_t total = 0;
for(size_t i = 0; i < elements_size(), ++i)
total += elements_[i].bytes();
size_t total = 0;
std::for_each(elements_.begin(), elements_.end(), count_bytes(total));
return total;
Neither one is "right."
What I want is to hide the details of iterating through a collection while revealing what is actually being done. In fact, I want to say:
(Python anyone?)
size_t total = 0;
for (each element in elements_)
total += element.bytes();
The "for-loop" approach fails on the "hide the iteration" criteria [although I've been using for loops for so long that for(size_t i = 0; i < elements_size(), ++i) is a single conceptual chunk for me.]
The "for-each" approach also fails to hide the iteration {although familiarity with STL makes begin() ... end() into a single conceptual chunk, also.]
The "for_each" approach also hides what's actually being done -- it depends on a descriptive name (count_bytes is not bad) to provide a hint.
The "for-loop" approach shows the actual work (which is good, but clutters it up with a leftover detail from the indexing process ("elements_[i]" rather than simply "element")
I wonder if there's some way to convince the compiler to recognize:
for any arbitrary collection (elements_) of data type (element). This would of course require that the collection obey STL rules.
size_t total = 0;
while(each(element, elements_))
total += element.bytes();
3 comments:
I'll bite...
namespace ahm {
template<typename C> //C is for container
bool each(typename C::const_iterator& iter, const C& container) {
if(iter == 0) iter = container.begin();
else ++iter;
if(iter == container.end()) return false;
return true;
}
}
namespace {
struct Widget {
int bytes_;
int bytes() const { return bytes_; }
};
int countem(const std::vector<Widget>& elements) {
using ahm::each;
size_t total = 0;
std::vector<Widget>::const_iterator iter = 0;
while(each(iter, elements)) {
total += iter->bytes();
}
return total;
}
void test() {
//as before...
}
}
Interesting, Adam. I'll play with it and maybe adopt it.
Minor quibble:
Rather than:
template<typename C> //C is for container
Why not just:
template<typename Container>
It's only in text books by mathemeticians that the template parameter names need to be one character long ;-)
Dale
I would have certainly used Container in real code but I was feeling lazy when writing up the sample (I guess it would have only been two more "Containers" but I didn't realize it at the time).
One option I considered was making the client set the iterator to the begin() point instead of using zero. The use of zero strikes me as a little odd and maybe non-standards-conforming.
For real code you'd want a non-const overload as well.
Post a Comment