Dear all,
In interviews with several people we recently had, I asked to read aloud and explain the following C++ code excerpt:
const int function_name( value_type const x )
{
return std::accumulate
( &x // a.
, &x + 1 // b.
, 0 // c.
, detail::count_function< value_type >() // d.
);
}
My intention was to write code that is easy to understand by companion C++ programmers. However, to my surprise, not one could explain the fragment, even though they knew about the STL and could tell that it comprises containers and algorithms, then again failing to mention that iterators connect those.
Having the detail::count_function class template already available, I preferred to write the above instead of:
const int function_name( value_type const x )
{
return detail::count_function< value_type >()( 0, x );
}
Completely opposite to my aim, the solution that uses std::accumulate was criticized as being unreadable. Of course, the names are chosen to be a little unhelpful in the interview situation, nevertheless I really hope you can guess that function_name may be about counting bits (set or cleared) in one object of type value_type and that detail::count_function() is a function object suitable for std::accumulate.
template< typename T >
class count_function : public std::binary_function<T, T, int>;
Then, this only is quite, ehm standard use of an algorithm. It appears that STL has not completely entered every C++ programmer's vocabulary yet. The containers are appreciated, algorithms fall behind.
Years ago, Kevlin Henney, already explored what happens when you apply a generic programming approach to string management in C++ in The Next Best String. It's all about standard algorithms used with std::string. If you've not yet read something by Kevlin, it's well worth it, he is a gifted writer of code and prose.
In his book Extended STL, Volume 1: Collections and Iterators, Matthew Wilson takes the container--algorithm--iterator concept even further: Containers broaden to collections, such as a file system, the registry and character streams.
As an exercise I wrote the WordIndex program that contains a tokeniser (or tokenizer if you're not in the UK) that provides an iterator interface. Reading from the text input stream is simply written as follows:
std::ostream& operator<< ( std::ostream& os, Tokenizer::value_type const value )
{
return os << "(" << value.first << "," << value.second << ")";
}
void copy_tokens( std::istream& is, std::ostream& os )
{
Tokenizer tokenizer( is );
std::copy
( tokenizer.begin() // input collection begin
, tokenizer.end() // input collection end
, std::ostream_iterator<Tokenizer::value_type>( os, "\n" )
);
}
int main()
{
copy_tokens( std::cin, std::cout );
}
Many, many kinds of collections are awaiting to have algorithms applied to them.
Happy writing!
Martin.
___
Resources:
- Kevlin Henney. The Next Best String (PDF, 76KB), C++ Workshop column in Application Development Advisor 6(8), October 2002.
- Matthew Wilson. Extended STL, Volume 1: Collections and Iterators. Addison–Wesley Professional, 2007. ISBN-10 0–321–30550–7, ISBN-13 978–0-321–30550–3.
- Martin Moene. WordIndex: create a linenumber cross-referenced list of words.