Boost C++ Libraries

[TODO]

C++ Standard Template Library (STL)

Let's Get Started with Examples of vector STL Template Class

In computing, a vector refers to an array-like structure that holds a set of direct-access elements of the same kinds, instead of mathematical n-component vector. Unlike array which is fixed-size, vector is dynamically-sized. vector is a class template, declared in the vector header.

vector is a template class. We create an int specialization via vector<int>. We create a vector<int> object via constructor vector<int> numbers(SIZE); which allocates SIZE elements and initializes to 0.

The size() member function returns the number of elements. The capacity() returns the storage allocated. All STL containers dynamically allocate storage.

Elements in vector has a linear order index. You can use [] overloaded operator or at() member function to access the n-th element. Take note that [] does not perform index-bound check; but at() does at runtime and throws out_of_range exception if index exceeds bound.

The member function front() and back() returns the first and last element respectively.

The default constructor vector<int> numbers construct a vector object with size of 0.

The member function push_back() appends the item at the end; while pop_back() removes the last element.

Example 3: Using iterator to access the container

We can use a special object called iterator to iterate through all the elements of a STL container, such as vector. The vector class provides a pair of functions begin() and end() to work with iterator. To use iterator:

// Declare a vector
vector<int> aVector(10);
// Declare an iterator called iter for vector<int>
vector<int>::iterator iter;
// Assign iter to the beginning of the vector
iter = aVector.begin()
// Use *iter to access the current element
cout << *iter << endl;
// Next element
++iter;
// The pass-the-end element is aVector.end() - to be excluded

Each container class defines its suitable iterator, with type name of vector<T>::iterator.

The vector's member function begin() and end() returns an iterator to the first element and the pass-the-end element, respectively. The pass-the-end element shall be excluded, i.e., [begin(), end()).

Iterator works like pointer, you can use *iter (dereferencing operator) to retrieve the vector element; ++iter (increment operator) to move to the next element; iter+n to point to the +n element.

The insert() and erase() member functions works on the iterator as well. insert(iter, item) inserts item before the iter-element. insert(insert, n, item) fills n element before the iter-element. erase(fist, last) removes all element in [first, last).

In C++11, you can use the auto as the type of iterator, which asks the compiler to deduce the type automatically.

priority_queue: highest priority element at front of the queue. adapted from vector (default) or deque. Support operations front, push_back, pop_front.

First-class Containers, Adapters and Near Containers

The containers can also be classified as:

First-class Containers: all sequence containers and associative containers are collectively known as first-class container.

Adapters: constrained first-class containers such as stack and queue.

Near Containers: Do not support all the first-class container operations. For example, the built-in array (pointer-like), bitsets (for maintaining a set of flags), valarray (support array computation), string (stores only character type).

Container's Functions

All containers provides these functions:

Default Constructor: to construct an empty container. Other constructors are provided for specific purposes.

Copy Constructor:

Destructor:

empty(): returns true if the container is empty.

size(): returns the size (number of elements).

Assignment Operator (=)

Comparison Operators (==, !=, <, <=, >, >=).

swap(): exchanges the contents of two containers.

In addition, the first-class containers support these functions:

begin, end, cbegin, cend: Returns the begin and end iterator, or the const version.

rbegin, rend, crbegin, crend: Returns the reverse_iterator.

clear(): Removes all elements.

erase(): Removes one element given an iterator, or a range of elements given [begin, end) iterators.

max_size(): Returns the maximum number of elements that the container can hold.

Container Header

<vector>

<list>

<deque>

<queue>: queue and priority_queue

<stack>

<map>: map and multimap

<set>: set and multiset

<valarray>

<bitset>

<array> (C++11)

<forward_list> (C++11)

<unordered_map> (C++11)

<unordered_set> (C++11)

Iterator

An iterator behaves like a generic pointer, which can be used to reference (point-to) individual element of a generic container; and transverse through elements of a container. The purpose of iterator is to make transversing (iterating) of containers independent on the type of the containers (e.g., vector<int>, queue<double>, stack<string>). With iterator, you can apply generic algorithm (such as searching, sorting and comparison) to the container, independent of types. Without iterator, you may need to write different codes for the same algorithm for different containers (e.g., different codes for searching an vector<int>, vector<double>, stack<string>).

Iterator abstracts pointer and works like pointer. It could actually be implemented as pointer, but that is totally up to the compiler. Iterator shall meet the following requirements:

The dereferencing operator * shall be defined. That is, if iter is an iterator, *iter shall be pointing to an element of the container.

The assignment operator = shall be defined. That is, if iter1 and iter2 are iterators, iter1 = iter2 shall assign iter2 to iter1.

The comparison operators == and != shall be defined. That is, if iter1 and iter2 are iterators, we can use iter1 == iter2 and iter1 != iter2 to compare them for equality. If iter1 == iter2 is true, then they shall be pointing at the same element, i.e., *iter1 == *iter2.

The increment operator ++ shall be defined. That is, if iter is an iterator, ++iter and iter++ move the iterator to point to the next element. The program shall be able to iterate through all the elements via ++iter (or iter++) operations.

In addition,

For linearly-ordered container, the + (and +=) operator shall be defined. That is, if iter is an iterator, iter+n points to the next n-th element in the linear order.

For iterator that can transverse backward, the decrement operator -- shall be defined. That is, if iter is an operator, --iter and iter-- move the iterator to point to the next element in the reverse order (or previous element in the forward order).

All STL container provides two member functions: begin() and end() that return the iterators pointing to the first element and the pass-the-end element respectively. Hence, you can use the following code to transverse all the elements in the container:

Take note that the above code work for all STL containers with any type specialization. The type of iterator (iter_type) depends on the container. In STL, you can get the iterator type via container<T>::iterator.

By convention, if a range of elements is specified by two iterators: first and last, then first is included and last is excluded, denoted as [first, last).

In C++11, you can use the auto to derive the type of iterator automatically, as follows:

Types of Iterators

Input Iterator: can be used to read element from a container (may not support write operation). It defines ++ (prefix and postfix) to transverse thru all the elements of a container in a single pass - but no guarantee that different passes will transverse through the elements in the same order. Input iterator can be used for single-pass, read-only algorithms.

Output Iterator: Similar to input iterator, but the dereferencing operator support write operation (may not support read operation). Output iterator can be used for single-pass, write-only algorithms.

Forward Iterator: the ++ operator transverses thru the elements, and always in the same order (in different passes). It support both read and write operations.

Bidirectional Iterator: a forward iterator with added support for -- (decrement, prefix and postfix) to transverse in the opposite direction.

In STL, each container class (such as vector) has a class scope typedef called iterator, which specifies the type of the iterator. For example, vector<int>'s iterator is called vector<int>::iterator; stack<string> is stack<string>::iterator.

It copies the elements in the range of [first,last) to the output range beginning at result. As mentioned, InputIterator shall provide read access and OutputIterator write access. Input and output could be the same container, but result cannot be in [first,last). For example,

Example: insert_iterator

The copy() with a OutputIterator (as in the above example) override the existing data in the output range. Instead you could use one of the insert_iterator to insert elements without overriding existing data. A front_insert_iterator inserts from the front; a back_insert_iterator inserts at the end; an insert_iterator inserts before a given location.

Algorithm

C++ provides a set of generic algorithm for STD in header <algorithm>, which includes:

Searching: find(), count().

Sorting: sort(), partial_sort(), merge().

Generation, mutation and deletion:

Numeric and relational:

The algorithms operate on elements of STL container only indirectly through the iterator.

The generic algorithms are non-member functions that are applicable to all STL containers. It accepts a pair of iterators, denoted as first and last, that mark the range of operation as [first,last) (including first, but excluding last). For example,

algorithm Functions

[TODO]

Function Object (Functors)

Most of the STL algorithms use so-called function objects or functors. A functor is an object that can be used with () operator, which includes regular functions, function pointers and class object with overloaded () operator.

for_each() algorithm

The for_each() algorithm, discussed earlier, takes a functor as its third argument, and apply the function to all the elements in the given range.

STL and the string class

The string class is not part of the STL, but has implemented many STL features. string can be treated as a STL container of char. It defines member functions begin(), end(), rbegin(), rend() which returns an iterator for forward and reverse transversal. Most of the algorithms (such as transform(), sort()) are applicable to string, operating on individual characters.

vector, valarray and array

vector

vector is certainly the most commonly used STL container. vector is dynamically allocated, with support for push_back() and insert().

array

The array class is a wrapper for the fixed-sized built-in array with the STL container interfaces. It is designed as a substitute for the built-in array type, for applications where dynamic resizable vector is not needed (so as to reduce the overhead of dynamic array). array does not support push_back() and insert(), as it cannot be resized.

valarray

valarray is designed for numeric computation. It is variable-size but does not supports STL operations such as push_back() or insert, but provides a simple interface for many mathematical operations. For example, the arithmetic operators (such as +, -, *, /, %) and mathematical functions (such as pow, sqrt, exp, log, sin, cos, etc.) are overloaded to operate on the entire valarray (instead of individual element). For example,

The STL container are template class, which can be instantiated with a type. The actual type has to be copy constructable (having copy constructor) and assignable (overload = operator).

Sequence Container

A sequence container requires that elements are arranged in a strict linear order.

vector: direct-access class-representation of dynamic array. Elements can be added and removed from the end in constant time. But insertion and removal not from the end require linear time. It supports direct-access, as well as bidirectional transversal.

deque: (pronounced "deck") double-ended queue, allow elements to be added and removed from both the front and the rear, at constant time. The deque implementation in STL is similar to vector, which allows direct access. It is more complex than vector, as it allows constant-time insertion and removal from the front and rear; whereas vector only for rear.

list: double-linked list that can be transverse in both direction. It support constant-time insertion and removal, but does not allow direct (random) access with no indexing operator.

forward_list (C++11): single-linked list that support forward transversal only. It is simpler than list.

queue: allow elements to be added at the rear and removed from the front at constant time. STL's queue is very restrictive that it does not support direct access nor transversal through the elements.

priority_queue: Similar to queue, but move the larger element to the front of the queue.

stack: LIFO (last-in-first-out) queue, elements can be added and removed from the top-of-stack in a last-in-first-out manner. In STL, stack is an adapter class over the vector class. It is more restrictive than vector. Elements can only be accessed, added and removed from one-end (top-of-stack). It does not support direct access, nor transversal through all the elements.

array (C++11): array is NOT a STL container because it has a fixed size and does not support operations like insert. But you can apply STL algorithms on array container.

Associative Containers

Associative container stores key-value pair or name-value pairs (i.e., associate a key with a value, and use a key to find the value). Associative container (or associative array) is actually similar to an array or vector, where a numerical index key is associated with a value, and you use the numerical key to find a value. Example of key-value pair are person-phone number(s), id-name, etc.

STL supports the following associative containers:

set: the key is the same as the value. It does not allow duplicate values. STL set is sorted and reversible.

multiset: allow duplicate values.

map: key-value pair, where keys are unique. One key is associated with one value. STL map is sorted and reversible. It needs two types to instantiate: map<key-type, value-type). To represent each key-value, STL provides a template class called pair<class K, class V>. You can instantiate the template class with specific key-type and value-type, e.g., pair<const int, string>.

multimap: one key could be associated with multiple values.

C++11 added 4 unordered associative containers: unordered_set, unordered_multiset, unordered_map, and unordered_multimap. These unordered associative containers are based on hash table (efficient in insertion, removal and search, but requires more storage spaces); whereas the ordered counterparts are based on tree.