Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
B.Eckel - Thinking in C++, Vol.2, 2nd edition.pdf
Скачиваний:
54
Добавлен:
08.05.2013
Размер:
2.09 Mб
Скачать

Creating your own STL-style algorithms

Once you become comfortable with the STL algorithm style, you can begin to create your own STL-style algorithms. Because these will conform to the format of all the other algorithms in the STL, they’re easy to use for programmers who are familiar with the STL, and thus become a way to “extend the STL vocabulary.”

The easiest way to approach the problem is to go to the <algorithm> header file and find something similar to what you need, and modify that (virtually all STL implementations provide the code for the templates directly in the header files). For example, an algorithm that stands out by its absence is copy_if( ) (the closest approximation is partition( )), which was used in Binder1.cpp at the beginning of this chapter, and in several other examples in this chapter. This will only copy an element if it satisfies a predicate. Here’s an implementation:

//: C05:copy_if.h

// Roll your own STL-style algorithm #ifndef COPY_IF_H

#define COPY_IF_H

template<typename ForwardIter,

typename OutputIter, typename UnaryPred>

OutputIter copy_if(ForwardIter begin, ForwardIter end, OutputIter dest, UnaryPred f) {

while(begin != end) { if(f(*begin))

*dest++ = *begin; begin++;

}

return dest;

}

#endif // COPY_IF_H ///:~

The return value is the past-the-end iterator for the destination sequence (the copied sequence).

Now that you’re comfortable with the ideas of the various iterator types, the actual implementation is quite straightforward. You can imagine creating an entire additional library of your own useful algorithms that follow the format of the STL.

Chapter 15: Multiple Inheritance

336

Summary

The goal of this chapter, and the previous one, was to give you a programmer’s-depth understanding of the containers and algorithms in the Standard Template Library. That is, to make you aware of and comfortable enough with the STL that you begin to use it on a regular basis (or at least, to think of using it so you can come back here and hunt for the appropriate solution). It is powerful not only because it’s a reasonably complete library of tools, but also because it provides a vocabulary for thinking about problem solutions, and because it is a framework for creating additional tools.

Although this chapter and the last did show some examples of creating your own tools, I did not go into the full depth of the theory of the STL that is necessary to completely understand all the STL nooks and crannies to allow you to create tools more sophisticated than those shown here. I did not do this partially because of space limitations, but mostly because it is beyond the charter of this book; my goal here is to give you practical understanding that will affect your day-to-day programming skills.

There are a number of books dedicated solely to the STL (these are listed in the appendices), but the two that I learned the most from, in terms of the theory necessary for tool creation, were first, Generic Programming and the STL by Matthew H. Austern, Addison-Wesley 1999 (this also covers all the SGI extensions, which Austern was instrumental in creating), and second (older and somewhat out of date, but still quite valuable), C++ Programmer’s Guide to the Standard Template Library by Mark Nelson, IDG press 1995.

Exercises

1.Create a generator that returns the current value of clock( ) (in <ctime>). Create a list<clock_t> and fill it with your generator using generate_n( ). Remove any duplicates in the list and print it to cout using copy( ).

2.Modify Stlshape.cpp from chapter XXX so that it uses transform( ) to delete all its objects.

3.Using transform( ) and toupper( ) (in <cctype>) write a single function call that will convert a string to all uppercase letters.

4.Create a Sum function object template that will accumulate all the values in a range when used with for_each( ).

5.Write an anagram generator that takes a word as a command-line argument and produces all possible permutations of the letters.

6.Write a “sentence anagram generator” that takes a sentence as a commandline argument and produces all possible permutations of the words in the sentence (it leaves the words alone, just moves them around).

7.Create a class hierarchy with a base class B and a derived class D. Put a virtual member function void f( ) in B such that it will print a message

Chapter 15: Multiple Inheritance

337

indicating that B’s f( ) has been called, and redefine this function for D to print a different message. Create a deque<B*> and fill it with B and D objects. Use for_each( ) to call f( ) for each of the objects in your deque.

8.Modify FunctionObjects.cpp so that it uses float instead of int.

9.Modify FunctionObjects.cpp so that it templatizes the main body of tests so you can choose which type you’re going to test (you’ll have to pull most of main( ) out into a separate template function).

10.Using transform( ), toupper( ) and tolower( ) (in <ccytpe>), create two functions such that the first takes a string object and returns that string with all the letters in uppercase, and the second returns a string with all the letters in lowercase.

11.Create a container of containers of Noisy objects, and sort them. Now write a template for your sorting test (to use with the three basic sequence containers), and compare the performance of the different container types.

12.Write a program that takes as a command line argument the name of a text file. Open this file and read it a word at a time (hint: use >>). Store each word into a deque<string>. Force all the words to lowercase, sort them, remove all the duplicates and print the results.

13.Write a program that finds all the words that are in common between two input files, using set_intersection( ). Change it to show the words that are not in common, using set_symmetric_difference( ).

14.Create a program that, given an integer on the command line, creates a “factorial table” of all the factorials up to and including the number on the command line. To do this, write a generator to fill a vector<int>, then use partial_sum( ) with a standard function object.

15.Modify CalcInventory.cpp so that it will find all the objects that have a quantity that’s less than a certain amount. Provide this amount as a command-line argument, and use copy_if( ) and bind2nd( ) to create the collection of values less than the target value.

16.Create template function objects that perform bitwise operations for &, |, ^ and ~. Test these with a bitset.

17.Fill a vector<double> with numbers representing angles in radians. Using function object composition, take the sine of all the elements in your vector (see <cmath>).

18.Create a map which is a cosine table where the keys are the angles in degrees and the values are the cosines. Use transform( ) with cos( ) (in <cmath>) to fill the table.

19.Write a program to compare the speed of sorting a list using list::sort( ) vs. using std::sort( ) (the STL algorithm version of sort( )). Hint: see the timing examples in the previous chapter.

20.Create and test a logical_xor function object template to implement a logical exclusive-or.

Chapter 15: Multiple Inheritance

338

21.Create an STL-style algorithm transform_if( ) following the first form of transform( ) which only performs transformations on objects that satisfy a unary predicate.

22.Create an STL-style algorithm which is an overloaded version of for_each( ) that follows the second form of transform( ) and takes two input ranges so it can pass the objects of the second input range a to a binary function which it applies to each object of the first range.

23.Create a Matrix class which is made from a vector<vector<int> >. Provide it with a friend ostream& operator<<(ostream&, const Matrix&) to display the matrix. Create the following using the STL algorithms where possible (you may need to look up the mathematical meanings of the matrix operations if you don’t remember them): operator+(const Matrix&, const Matrix&) for Matrix addition, operator*(const Matrix&, const vector<int>&) for multiplying a matrix by a vector, and operator*(const Matrix&, const Matrix&) for matrix multiplication. Demonstrate each.

24.Templatize the Matrix class and associated operations from the previous example so they will work with any appropriate type.

Chapter 15: Multiple Inheritance

339

Part 2: Advanced

Topics

341

Соседние файлы в предмете Численные методы
  • #
    08.05.20133.99 Mб23A.Menezes, P.van Oorschot,S.Vanstone - HANDBOOK OF APPLIED CRYPTOGRAPHY.djvu
  • #
  • #
    08.05.20135.91 Mб26B.Eckel - Thinking in Java, 3rd edition (beta).pdf
  • #
  • #
    08.05.20136.09 Mб18D.MacKay - Information Theory, Inference, and Learning Algorithms.djvu
  • #
    08.05.20133.85 Mб17DIGITAL Visual Fortran ver.5.0 - Programmers Guide to Fortran.djvu
  • #
    08.05.20131.84 Mб15E.A.Lee, P.Varaiya - Structure and Interpretation of Signals and Systems.djvu