- •Вычисления значений
- •Пример:
- •Вычисления типов
- •Преимущества мета подхода:
- •Польза использования mpl:
- •Числовая метафункция
- •Свойства
- •Метаданные
- •Специализация
- •Первичный шаблон:
- •Инстанцирование:
- •Метафункции
- •Полиморфизм
- •Возможности свойств:
- •Организация свойств в Boost:
- •Пример:
- •Типовые ассоциации
- •Альтернатива:
- •Метафункции Продвижение (пересылка) метафункций
- •Класс метафункции
- •Формат:
- •Числовые
- •Пример:
- •Нульарные
- •Метрический анализ (Анализ размерностей)
- •Метрики
- •Величины
- •Сложение и вычитание
- •Умножение
- •Класс метафункции
- •Деление
- •Пример:
- •Метафункции высшего порядка (Каскады вложенных вызовов)
- •Использование apply:
- •Заполнители
- •Безымянный заполнитель:
- •Определение выражений с заполнителями
- •Лямбда (Лямбда метафункции/выражения)
- •Частичное приложение метафункции
- •Лямбда и Шаблоны Неметафункции
- •Обертки
- •Выбор типа
- •Ленивый Выбор Типа
- •Логические Операторы
- •Целочисленные обертки
- •Составные Операторы
- •Операторы с булевым значением:
- •Операторы для сравнения значений:
- •Операторы для интегральных значений:
- •Побитовые операторы:
- •Арифметические операторы:
- •Целочисленная «стенография»
- •Интегральные последовательности
- •Формат:
- •Последовательности
- •Концепции
- •Итераторы
- •Двунаправленные
- •Произвольные
- •Последовательности
- •Двунаправленные
- •Произвольные
- •Расширенные
- •Ассоциативные
- •Требования
- •Расширения
- •Расширенные ассоциативные последовательности
- •Алгоритмы и последовательности
- •Итераторы
- •Равенство
- •Операции Внутренние операции с последовательностей
- •Наследование
- •Создание последовательности
- •Реализация:
- •Создание итератора
- •Преимущества полной специализации перед частичной:
- •Добавление расширения
- •Алгоритмы
- •Абстракция:
- •Stl алгоритмы
- •Детали правильного использования stl:
- •Mpl алгоритмы
- •Различия stl и mpl алгоритмов:
- •Пример:
- •Вставки
- •Пример 1:
- •Пример 2:
- •Пример 3:
- •Фундамент алгоритмов
- •Пример:
- •Запрашиваемые алгоритмы
- •Последовательности (Алгоритмы, создающие последовательности)
- •Синонимы функциональных алгоритмов:
- •Создание алгоритма
- •Итераторы «Просмотр» и итераторы-адаптеры
- •Концепция просмотра
- •Применение просмотра Сравнения значений элементов последовательности:
- •Объединение множественных (мульти-) последовательностей
- •Упрощение 1
- •Упрощение 2 (создание просмотра)
- •Уход от ненужного вычисления
- •Выборочная обработка элемента
- •Итератор-адаптер
- •Создание просмотра
- •Реализация итератора-адаптера для zip_view.
- •Диагностика
- •Отладка ошибок
- •Трассировка инстанцирования
- •Исправленный пример:
- •Форматы сообщений об ошибках
- •Блок «with»
- •Устранение параметров шаблона по умолчанию
- •Глубокий typedef
- •Инструменты
- •Несколько компиляторов
- •(Статические Утверждения)
- •Формат:
- •Формат:
- •Индивидуальные сообщения утверждений
- •Настройка предиката:
- •(Генерирование встроенных сообщений)
- •Формат:
- •Выбор стратегии:
- •Тип печати
- •Кросс этапность компиляции/выполнения
- •Печать типов:
- •Тип посещения:
- •Выбор реализаций
- •Специализация шаблонов классов
- •Тег диспетчеризации
- •Выбор структуры
- •Композиция классов
- •Указатели на функцию
- •Ослабление типизации
- •Пример:
- •Обобщение:
- •Динамический полиморфизм
- •Автоматизация
- •Сохранение интерфейса
- •Рекуррентный шаблон
- •Формат:
- •Генерирование функций
- •Управление разрешением перегрузки
- •Явное управление множеством перегрузки
- •Документация mpl Последовательности
- •Концепции
- •(Прямая последовательность)
- •(Двунаправленная Последовательность)
- •(Последовательность произвольного доступа)
- •(Расширенная последовательность)
- •(Расширенная последовательность начала)
- •(Расширенная последовательность конца)
- •(Ассоциативная последовательность)
- •(Расширенная ассоциативная последовательность)
- •(Обертка интегральной последовательности )
- •(Переменная последовательность)
- •Представления
- •Метафункции (Внутренние)
- •Итераторы
- •Концепции
- •(Прямой итератор)
- •(Двунаправленный итератор)
- •(Итератор произвольного доступа)
- •Метафункции
- •Алгоритмы
- •Концепции
- •(Инсертер: механизм вставок)
- •Инсертеры (инсертер: механизм вставок)
- •Итеративные алгоритмы
- •Запрашиваемые алгоритмы
- •Преобразования
- •Метафункции
- •Концепции Метафункция
- •Метафункциональный класс
- •Лямбда выражения
- •Заполнители
- •Тэг диспетчеризированные метафункции
- •Числовые метафункции
- •Тривиальные метафункции
Stl алгоритмы
Алгоритмы STL представляют собой мощные абстракции, работа которых поддерживается другими абстракциями и сокрыта от пользователя, это делает использование алгоритма очень гибким, но со своими нюансами:
Рассмторим 2 альтернативные версии прибавления числа 42 к каждому элементу последовательности:
// "abstraction"
std::transform(
v.begin(), v.end(), v.begin(),
std::bind2nd(std::plus<int>(),42)
);
// handwritten loop
typedef std::vector<int>::iterator v_iter;
for(v_iter i = v.begin(), last = v.end(); i != last; ++i)
*i += 42;
При явном использовании циклов с контейнерами приходиться также явно использовать абстракцию итераторов, для обхода последовательности. Такой способ создания функторов является громоздким и привносит, по крайней мере, столько же низкоуровневых деталей сколько и скрывает.
Эти недостатки, однако, могут быть преодолены довольно легко. Например, мы можем использовать библиотеку Boost Lambda, которая стала прообразом лямбд в MPL, лямбды помогут упростить и прояснить работу с функторами времени выполнения.
В следующих примерах заполнительно «_1» ссылается на прототип объекта из библиотеки Boost Lambda (в пространстве имен boost::lambda). Заполнители времени выполнения из Boost Lambda явялются прообразами заполнителей MPL.
std::transform(v.begin(), v.end(), v.begin(), _1 + 42);
или так:
std::for_each(v.begin(), v.end(), _1 += 42);
Обе инструкции делают тоже, что и циклы выше, но механизмы Lambda, привносят чистоту и ясность в работу с алгоритмами.
По примеру видно, что проблема не в алгоритме, а в том как его используют. Основной проблемой была STL среда для генерирования аргумента для функции алгоритма.
Детали правильного использования stl:
Создание временных итераторов.
Правильные объявления типа итераторов, даже в обобщенном коде.
Избегание неэффективности: если эффективность играет важную роль, то лучше избегать постфиксной инкрементации (и++), так как реализация оператор++ должна сделать копию итератора перед его увеличением, чтобы вернуть исходное значение (копию), но изменить оригинал. Разработчики стандартной библиотеки знают об этом и применяют префиксную форму (++и) везде, где возможно.
Использование известных оптимизаций (например, раскрутка цикла).
Обобщенные условие завершения циклов: например, алгоритм for_each использует pos != finish, а не pos < finish, т.к. в противном случае, в данном алгоритме нельзя было бы использовать итератор произвольного доступа.
Несоблюдение таких деталей может привести к большим проблемам, тем более, что это лишь верхний уровень проблемных мест.
Использование for_each позволяет раздельно решать проблемы: паттерн может выполнять обход и модификацию всех элементов последовательности, пользователю предоставлена возможность настраивать детали работы алгоритма. На этапе компиляции, это разделение может быть особенно важно, т.к. кодирование даже самых простых повторяющихся процессов не так просто. Это большое преимущество, чтобы иметь возможность использовать уже написанные библиотеки алгоритмов, добавив только детали, которые относятся к конкретной проблеме, которую вы на самом деле пытаетесь решить.
