Tuesday, January 21, 2014

back_inserter c++

STL back_inserter c++ : Standard Template Library Tutorial, ccplusplus.com
Iterators are pure abstractions: Anything that behaves like an iterator is an iterator. For this reason, you can write classes that have the interface of iterators but do something (completely) different. The C++ standard library provides several predefined special iterators: iterator adapters. They are more than auxiliary classes; they give the whole concept a lot more power.

The following subsections introduce three iterator adapters:
  1. Insert iterators
  2. Stream iterators
  3. Reverse iterators

Insert Iterators

The first example of iterator adapters are insert iterators, or inserters. Inserters are used to let algorithms operate in insert mode rather than in overwrite mode. In particular, they solve the problem of algorithms that write to a destination that does not have enough room: They let the destination grow accordingly.
Insert iterators redefine their interface internally as follows:
  • If you assign a value to their actual element, they insert that value into the collection to which they belong. Three different insert iterators have different abilities with regard to where the elements are inserted — at the front, at the end, or at a given position.
  • A call to step forward is a no-op.
Consider the following example:

This example uses all three predefined insert iterators:
  1. Back inserters
    Back inserters insert the elements at the back of their container (appends them) by calling push_back(). For example, with the following statement, all elements of coll1 are appended into coll2:

    Of course, back inserters can be used only for containers that provide push_back() as a member function. In the C++ standard library, these containers are vector, deque, and list.
  2. Front inserters
    Front inserters insert the elements at the front of their container by calling push_front(). For example, with the following statement, all elements of coll1 are inserted into coll3:

    Note that this kind of insertion reverses the order of the inserted elements. If you insert 1 at the front and then 2 at the front, the 1 is after the 2.
    Front inserters can be used only for containers that provide push_front() as a member function. In the C++ standard library, these containers are deque and list.
  3. General inserters
    A general inserter, also called simply an inserter, inserts elements directly in front of the position that is passed as the second argument of its initialization. It calls the insert() member function with the new value and the new position as arguments. Note that all predefined containers have such an insert() member function. This is the only predefined inserter for associative containers.
    But wait a moment. I said that you can't specify the position of a new element in an associative container because the positions of the elements depend on their values. The solution is simple: For associative containers, the position is taken as a hint to start the search for the correct position. If the position is not correct, Table below describes a user-defined inserter that is more useful for associative containers.
Table : Predefined Insert Operators

Kind of Inserter
back_inserter (container)
Appends in the same order by using push_back()
front_inserter (container)
Inserts at the front in reverse order by using push_front()
inserter (container ,pos)
Inserts at pos (in the same order) by using insert()

Stream Iterators

Another very helpful kind of iterator adapter is a stream iterator. Stream iterators are iterators that read from and write to a stream (A stream is an object that represents I/O channels). Thus, they provide an abstraction that lets the input from the keyboard behave as a collection, from which you can read. Similarly you can redirect the output of an algorithm directly into a file or onto the screen.

Consider the following example. It is a typical example of the power of the whole STL. Compared with ordinary C or C++, it does a lot of complex processing by using only a few statements:

The program has only three statements that read all words from the standard input and print a sorted list of them. Let's consider the three statements step-by-step. In the statement

two input stream iterators are used:
  1. The expression

    creates a stream iterator that reads from the standard input stream cin. The template argument string specifies that the stream iterator reads elements of this type. These elements are read with the usual input operator >>. Thus, each time the algorithm wants to process the next element, the istream iterator transforms that desire into a call of

    The input operator for strings usually reads one word separated by whitespaces, so the algorithm reads word-by-word.
  2. The expression

    calls the default constructor of istream iterators that creates an end-of-stream iterator. It represents a stream from which you can no longer read.
As usual, the copy() algorithm operates as long as the (incremented) first argument differs from the second argument. The end-of-stream iterator is used as the end of the range, so the algorithm reads all strings from cin until it can no longer read any more (due to end-of-stream or an error). To summarize, the source of the algorithm is "all words read from cin." These words are copied by inserting them into coll with the help of a back inserter.

The sort() algorithm sorts all elements:

Lastly, the statement

copies all elements from the collection into the destination cout. During the process, the unique_copy() algorithm eliminates adjacent duplicate values. The expression

creates an output stream iterator that writes strings to cout by calling operator >> for each element. The second argument behind cout serves as a separator between the elements. It is optional. In this example, it is a newline, so every element is written on a separate line.

All components of the program are templates, so you can change the program easily to sort other value types, such as integers or more complex objects. 

In this example, one declaration and three statements were used to sort all words from standard input. However, you could do the same by using only one declaration and one statement. 

Reverse Iterators

The third kind of predefined iterator adapters are reverse iterators. Reverse iterators operate in reverse. They switch the call of an increment operator internally into a call of the decrement operator, and vice versa. All containers can create reverse iterators via their member functions rbegin() and rend(). Consider the following example:

The expression

returns a reverse iterator for coll. This iterator may be used as the beginning of a reverse iteration over the elements of the collection. Its position is the last element of the collection. Thus, the expression

returns the value of the last element.
Accordingly, the expression

returns a reverse iterator for coll that may be used as the end of a reverse iteration. As usual for ranges, its position is past the end of the range, but from the opposite direction; that is, it is the position before the first element in the collection.
The expression

is as undefined as is

You should never use operator * (or operator ->) for a position that does not represent a valid element.

The advantage of using reverse iterators is that all algorithms are able to operate in the opposite direction without special code. A step to the next element with operator ++ is redefined into a step backward with operator --. For example, in this case, copy() iterates over the elements of coll from the last to the first element. So, the output of the program is as follows:

You can also switch "normal" iterators into reverse iterators, and vice versa. However, in doing so the element of an iterator changes. 

See Also:


No comments:

Post a Comment