66.4964, 66.6965 Design and Implementation of Generic Software

Prof. David Musser
Dr. Sibylle Schupp
Spring 1997

Generic Programming with Templates

Main application of generic programming: Developing and organizing libraries of reusable software components.

We now focus on templates, paying some attention also to function inlining and operator overloading.

Plan for this and next three sessions (subject to change):

  1. Template basic ideas and terminology; overview of STL
  2. Large example: Template counting classes for generic algorithm performance measurement
  3. Identifying and documenting template parameter restrictions: the SGI STL web pages; the BALM project
  4. Dealing with template problems (e.g., code bloat); far-out uses of templates (expression templates, template meta-programs).

Template basics and terminology

We will assume some prior experience with templates, so the focus will be on ensuring a common vocabulary and, based on your questions, noting things we need to cover in the next three sessions.

Terminology used by ANSI/ISO committee

Subject to change, see Carroll and Ellis, p. ix.

The infamous pair class template

template <class T1, class T2>
struct pair {
    T1 first;
    T2 second;
    pair() : first(T1()), second(T2()) {}
    pair(const T1& a, const T2& b) : first(a), second(b) {}
};

Function inlining: another C++ feature that supports generic programming

Template member functions

Default template parameters

STL: Overview and Small Examples

The Standard Template Library is a(n almost standard) C++ library that provides a set of easily composable data structures (template classes) and generic algorithms (template functions).

At its July 1994 meeting, the ANSI/ISO C++ Standards Committee voted to adopt STL as part of the standard C++ library. It has been incorporated into the full standard and is now supported, at least partially, by several major compiler vendors.

We will look at numerous small STL examples, mostly from Chapters 1, 2, 5, and 6 of David R. Musser & Atul Saini, STL Tutorial and Reference Guide: C++ Programming with the Standard Template Library, Addison-Wesley, 1996. (Hereafter referred to as M&S.) The examples are also online in STL examples. Links to particular programs are also included in the discussion in these notes.

The assert macro

The assert macro with STL

Overview of STL components

STL contains six major kinds of components: containers, generic algorithms, iterators, function objects, adaptors, and allocators. These are all designed to fit together in many different combinations.

STL containers (data abstractions)

STL generic algorithms

There are many useful algorithms that can be done on sequence containers, such as searching, merging, copying, sorting, etc., in many different variations. In STL most of these these are not implemented as member functions of the sequence container classes. Instead the containers and the algorithms are designed so that each algorithm can be used with different container classes. Because of their generality such algorithms are called generic algorithms. Two of the simplest generic algorithms in STL are find and merge.

This flexibility is due in large part to the way STL connects containers and algorithms together using iterators, which are pointer-like objects. Having different kinds of iterators for different containers allows the same algorithm to work with different containers while still doing ``the same thing'' (abstractly). Iterators are discussed in detail in Section 2-3 and Chapter 4 of M&S.

Iterators

STL connects data structures and algorithms together using iterators, which are pointer-like objects used to gain access to all elements of a linear sequence. STL defines a set of requirements an object must satisfy to be an iterator.

The way STL generic algorithms use iterators is illustrated by the accumulate algorithm.

template <class InputIterator, class T>
T accumulate(InputIterator first, InputIterator last, T init) {
    while (first != last) {
        init = init + *first;
        ++first;
    }
    return init;
}

The precise definition of these iterator categories is given in Chapter 4 of Musser & Saini. The key point to understand is some algorithms need the more powerful iterators in order to operate efficiently. For example linear searching only needs input iterators, but sorting needs random access iterators.

Function objects

Definition of generic algorithms in terms of iterators makes the algorithms very flexible, but even more flexibility is afforded by other parameters called function objects.

Adaptors

An STL adaptor is a component that modifies the interface of another component.

Organization and Examples of STL Generic Algorithms

In-place and copying versions

Algorithms with Function Parameters

Categories of STL Generic Algorithms

STL generic algorithms fall into four broad categories.

Nonmutating sequence algorithms.

If you need some algorithm for searching a sequence or counting elements that have some property, check out the algorithms in this category. They are called nonmutating because they don't change the sequence to which they are applied.

Mutating sequence algorithms.

Those algorithms that do change sequences, but are not related to sorting (the next category), reside here. E.g., copying, filling, generating, partitioning, shuffling, removing elements, rotating, and transforming.

Sorting-related algorithms.

This category includes sorting; merging; and set operations on sorted sequences, such as union and intersection. Maintaining a heap, which can be used as a priority queue, is also provided. Also, comparing two sequences lexicographically (a generalization of alphabetical ordering of strings) and generating all permutations of a sequence in lexicographical order.

Generalized numeric algorithms.

This category contains algorithms like accumulate for computing sums, sequences of partial sums, and inner products---all suitably generalized with function object parameters so you can substitute other binary operations for + and *.