Выбрать главу

template ‹class T›

inline random_access_iterator_tag iterator_category(const T*) {

 return random_access_iterator_tag();

}

// value_type of iterator (функции значимого типа итераторов)

template ‹class T, class Distance›

inline T* value_type(const input_iterator‹T, Distance›&) {

 return (T*) (0);

}

template ‹class T, class Distance›

inline T* value_type(const forward_iterator‹T, Distance›&) {

 return (T*) (0);

}

template ‹class T, class Distance›

inline T* value_type(const bidirectional_iterator‹T, Distance›&) {

 return (T*) (0);

}

template ‹class T, class Distance›

inline T* value_type(const random_access_iterator‹T, Distance›&) {

 return (T*) (0);

}

template ‹class T›

inline T* value_type(const T*) {return (T*) (0);}

// distance_type of iterator (функции типа расстояния итераторов)

template ‹class T, class Distance›

inline Distance* distance_type(const input_iterator‹T, Distance›&) {

 return (Distance*) (0);

}

template ‹class T, class Distance›

inline Distance* distance_type(const forward_iterator‹T, Distance›&) {

 return (Distance*) (0);

}

template ‹class T, class Distance›

inline Distance* distance_type(const bidirectional_iterator‹T, Distance›&) {

 return (Distance*) (0);

}

template ‹class T, class Distance›

inline Distance* distance_type(const random_access_iterator‹T, Distance›&) {

 return (Distance*) (0);

}

template ‹class T›

inline ptrdiff_t* distance_type(const T*) {return (ptrdiff_t*) (0);}

Если пользователь хочет определить двунаправленный итератор для некоторой структуры данных, содержащей double, и такой, чтобы работал с большой (large) моделью памяти компьютера, то это может быть сделано таким определением:

class MyIterator: public bidirectional_iterator ‹double, long› {

 // код, осуществляющий ++, и т.д.

};

Тогда нет необходимости определять iterator_category, value_type, и distance_type в MyIterator.

Операции с итераторами (Iterator operations)

Так как только итераторы произвольного доступа обеспечивают + и - операторы, библиотека предоставляет две шаблонные функции advance и distance. Эти функции используют + и - для итераторов произвольного доступа (и имеют, поэтому, сложность постоянного времени для них); для итераторов ввода, последовательных и двунаправленных итераторов функции используют ++, чтобы обеспечить реализацию со сложностью линейного времени. advance берет отрицательный параметр n только для итераторов произвольного доступа и двунаправленных итераторов. advance увеличивает (или уменьшает для отрицательного n) итераторную ссылку i на n. distance увеличивает n на число единиц, сколько требуется, чтобы дойти от first до last.

template ‹class InputIterator, class Distance›

inline void advance(InputIterator& i, Distance n);

template ‹class InputIterator, class Distance›

inline void distance(InputIterator first, InputIterator last, Distance& n);

distance должна быть функцией 3-х параметров, сохраняющей результат в ссылке вместо возвращения результата, потому что тип расстояния не может быть выведен из встроенных итераторных типов, таких как int*.

Функциональные объекты

Функциональные объекты - это объекты, для которых определён operator(). Они важны для эффективного использования библиотеки. В местах, где ожидается передача указателя на функцию алгоритмическому шаблону, интерфейс установлен на приём объекта с определённым operator(). Это не только заставляет алгоритмические шаблоны работать с указателями на функции, но также позволяет им работать с произвольными функциональными объектами. Использование функциональных объектов вместе с функциональными шаблонами увеличивает выразительную мощность библиотеки также, как делает результирующий код более эффективным. Например, если мы хотим поэлементно сложить два вектора a и b, содержащие double, и поместить результат в a, мы можем сделать зто так:

transform(a.begin(), a.end(), b.begin(), a.begin(), plus‹double›());

Если мы хотим отрицать каждый элемент a, мы можем сделать это так:

transform(a.begin(), a.end(), a.begin(), negate‹double›());

Соответствующие функции вставят сложение и отрицание.

Чтобы позволить адаптерам и другим компонентам манипулировать функциональными объектами, которые используют один или два параметра, требуется, чтобы они соответственно обеспечили определение типов (typedefs) argument_type и result_type для функциональных объектов, которые используют один параметр, и first_argument_type, second_argument_type и result_type для функциональных объектов, которые используют два параметра.

Базовые классы (Base)

Следующие классы предоставляются, чтобы упростить определение типов (typedefs) параметров и результата:

template ‹class Arg, class Result›

struct unary_function {

 typedef Arg argument_type;

 typedef Result result_type;

};

template ‹class Arg1, class Arg2, class Result›

struct binary_function {

 typedef Arg1 first_argument_type;

 typedef Arg2 second_argument_type;

 typedef Result result_type;

};

Арифметические операции (Arithmetic operations)

Библиотека обеспечивает базовые классы функциональных объектов для всех арифметических операторов языка.

template ‹class T›

struct plus: binary_function‹T, T, T› {

 Т operator()(const T& x, const T& y) const {return x + y;}

};

template ‹class T›

struct minus: binary_function‹T, T, T› {

 Т operator()(const T& x, const T& y) const {return x - y;}

};

template ‹class T›

struct times: binary_function‹T, T, T› {

 Т operator()(const T& x, const T& y) const (return x * y;}

};

template ‹class T›

struct divides: binary_function‹T, T, T› {

 Т operator()(const T& x, const T& y) const {return x / y;}

};

template ‹class T›

struct modulus: binary_function‹T, T, T› {

 Т operator()(const T& x, const T& y) const {return x % y;}

};

template ‹class T›

struct negate: unary_function‹T, T› {