: public unary_function typename F1::result_type> { public: unary_composer(F1 f1, F2 f2) : f1(f1), f2(f2) {} typename F1::result_type operator()(typename F2::argument_type x) { return f1(f2(x)); } private: F1 f1; F2 f2; }; template unary_composer return unary_composer } int main() { const int sz = 9; vector // Fill it with random number strings: generate(vs.begin(), vs.end(), NumStringGen()); copy(vs.begin(), vs.end(), ostream_iterator cout << endl; vector transform(vs.begin(), vs.end(), back_inserter(vd), compose(ptr_fun(atof), mem_fun_ref(&string::c_str))); copy(vd.begin(), vd.end(), ostream_iterator cout << endl; } ///:~ Once again we must use typename to let the compiler know that the member we are referring to is a nested type. Some implementations[85] support composition of function objects as an extension, and the C++ standards committee is likely to add these capabilities to the next version of standard C++.
A catalog of STL algorithms
This section provides a quick reference for when you’re searching for the appropriate algorithm. We leave the full exploration of all the STL algorithms to other references (see the end of this chapter, and Appendix A), along with the more intimate details of performance, and so on. Our goal here is for you to become rapidly comfortable and facile with the algorithms, and we’ll assume you will look into the more specialized references if you need more depth of detail.
Although you will often see the algorithms described using their full template declaration syntax, we’re not doing that here because you already know they are templates, and it’s quite easy to see what the template arguments are from the function declarations. The type names for the arguments provide descriptions for the types of iterators required. We think you’ll find this form is easier to read, and you can quickly find the full declaration in the template header file if for some reason you feel the need.
The reason for all the fuss about iterators is to accommodate any type of container that meets the requirements in the standard library. So far we have illustrated the generic algorithms with only arrays and vectors as sequences, but in the next chapter you’ll see a broad range of data structures that support less robust iteration. For this reason, the algorithms are categorized in part by the types of iteration facilities they require.
The names of the iterator classes describe the iterator type to which they must conform. There are no interface base classes to enforce these iteration operations—they are just expected to be there. If they are not, your compiler will complain. The various flavors of iterators are described briefly as follows.
InputIterator. An input iterator only allows
OutputIterator. An output iterator only allows