However, the more elaborate types from Table G.1 can also be used in more general code in which the type of container and element are generic. For example, suppose you want a min() function that takes as its argument a reference to a container and returns the smallest item in the container. This assumes that the < operator is defined for the value type used to instantiate the template and that you don’t want to use the STL min_element() algorithm, which uses an iterator interface. Because the argument could be vector or list or deque, you use a template with a template parameter, such as Bag, to represent the container. (That is, Bag is a template type that might be instantiated as vector, list, or some other container type.) So the argument type for the function is const Bag & b. What about the return type? It should be the value type for the container—that is, Bag::value_type. However, at this point, Bag is just a template parameter, and the compiler has no way of knowing that the value_type member is actually a type. But you can use the typename keyword to clarify that a class member is a typedef:

vector::value_type st;    // vector a defined class

typename Bag::value_type m;       // Bag an as yet undefined type

For the first definition here, the compiler has access to the vector template definition, which states that value_type is a typedef. For the second definition, the typename keyword promises that, whatever Bag may turn out to be, the combination Bag::value_type is the name of a type. These considerations lead to the following definition:

template

typename Bag::value_type min(const Bag & b)

{

    typename Bag::const_iterator it;

    typename Bag::value_type m = *b.begin();

    for (it = b.begin(); it != b.end(); ++it)

        if (*it < m)

            m = *it;

    return m;

}

You then could use this template function as follows:

vector temperatures;

// input temperature values into the vector

int coldest = min(temperatures);

The temperatures parameter would cause Bag to be evaluated as vector and typename Bag::value_type to be evaluated as vector::value_type, which, in turn, is int.

All containers also contain the member functions or operations listed in Table G.2. Again, X is a container type, such as vector, and T is the type stored in the container, such as int. Also a and b are values of type X, u is an identifier, r is a non-const value of type X, and rv is a non-const rvalue of type X. The move operations were added by C++11.

Table G.2. Operations Defined for All Containers

Containers that use a bi-directional or random iterator (vector, list, deque, queue, array, set, and map) are reversible and provide the methods in Table G.3.

Table G.3. Types and Operations Defined for Reversible Containers

The unordered set and unordered map containers are not required to support the optional container operations in Table G.4, but the remaining containers do support them.

Table G.4. Optional Container Operations

The > operator for a container assumes that the > operator is defined for the value type. A lexicographic comparison is a generalization of alphabetical sorting. It compares two containers, element-by-element, until it encounters an element in one container that doesn’t equal the corresponding element in the other container. In that case, the containers are considered to be in the same order as the noncorresponding pair of elements. For example, if two containers are identical through the first 10 elements, but the 11th element in the first container is less than the 11th element in the second container, the first container precedes the second. If two containers compare equally until one runs out of elements, the shorter container precedes the longer.

Additional Members for Sequence Containers

Перейти на страницу:

Все книги серии Developer's Library

Похожие книги