- •Вычисления значений
- •Пример:
- •Вычисления типов
- •Преимущества мета подхода:
- •Польза использования mpl:
- •Числовая метафункция
- •Свойства
- •Метаданные
- •Специализация
- •Первичный шаблон:
- •Инстанцирование:
- •Метафункции
- •Полиморфизм
- •Возможности свойств:
- •Организация свойств в Boost:
- •Пример:
- •Типовые ассоциации
- •Альтернатива:
- •Метафункции Продвижение (пересылка) метафункций
- •Класс метафункции
- •Формат:
- •Числовые
- •Пример:
- •Нульарные
- •Метрический анализ (Анализ размерностей)
- •Метрики
- •Величины
- •Сложение и вычитание
- •Умножение
- •Класс метафункции
- •Деление
- •Пример:
- •Метафункции высшего порядка (Каскады вложенных вызовов)
- •Использование apply:
- •Заполнители
- •Безымянный заполнитель:
- •Определение выражений с заполнителями
- •Лямбда (Лямбда метафункции/выражения)
- •Частичное приложение метафункции
- •Лямбда и Шаблоны Неметафункции
- •Обертки
- •Выбор типа
- •Ленивый Выбор Типа
- •Логические Операторы
- •Целочисленные обертки
- •Составные Операторы
- •Операторы с булевым значением:
- •Операторы для сравнения значений:
- •Операторы для интегральных значений:
- •Побитовые операторы:
- •Арифметические операторы:
- •Целочисленная «стенография»
- •Интегральные последовательности
- •Формат:
- •Последовательности
- •Концепции
- •Итераторы
- •Двунаправленные
- •Произвольные
- •Последовательности
- •Двунаправленные
- •Произвольные
- •Расширенные
- •Ассоциативные
- •Требования
- •Расширения
- •Расширенные ассоциативные последовательности
- •Алгоритмы и последовательности
- •Итераторы
- •Равенство
- •Операции Внутренние операции с последовательностей
- •Наследование
- •Создание последовательности
- •Реализация:
- •Создание итератора
- •Преимущества полной специализации перед частичной:
- •Добавление расширения
- •Алгоритмы
- •Абстракция:
- •Stl алгоритмы
- •Детали правильного использования stl:
- •Mpl алгоритмы
- •Различия stl и mpl алгоритмов:
- •Пример:
- •Вставки
- •Пример 1:
- •Пример 2:
- •Пример 3:
- •Фундамент алгоритмов
- •Пример:
- •Запрашиваемые алгоритмы
- •Последовательности (Алгоритмы, создающие последовательности)
- •Синонимы функциональных алгоритмов:
- •Создание алгоритма
- •Итераторы «Просмотр» и итераторы-адаптеры
- •Концепция просмотра
- •Применение просмотра Сравнения значений элементов последовательности:
- •Объединение множественных (мульти-) последовательностей
- •Упрощение 1
- •Упрощение 2 (создание просмотра)
- •Уход от ненужного вычисления
- •Выборочная обработка элемента
- •Итератор-адаптер
- •Создание просмотра
- •Реализация итератора-адаптера для zip_view.
- •Диагностика
- •Отладка ошибок
- •Трассировка инстанцирования
- •Исправленный пример:
- •Форматы сообщений об ошибках
- •Блок «with»
- •Устранение параметров шаблона по умолчанию
- •Глубокий typedef
- •Инструменты
- •Несколько компиляторов
- •(Статические Утверждения)
- •Формат:
- •Формат:
- •Индивидуальные сообщения утверждений
- •Настройка предиката:
- •(Генерирование встроенных сообщений)
- •Формат:
- •Выбор стратегии:
- •Тип печати
- •Кросс этапность компиляции/выполнения
- •Печать типов:
- •Тип посещения:
- •Выбор реализаций
- •Специализация шаблонов классов
- •Тег диспетчеризации
- •Выбор структуры
- •Композиция классов
- •Указатели на функцию
- •Ослабление типизации
- •Пример:
- •Обобщение:
- •Динамический полиморфизм
- •Автоматизация
- •Сохранение интерфейса
- •Рекуррентный шаблон
- •Формат:
- •Генерирование функций
- •Управление разрешением перегрузки
- •Явное управление множеством перегрузки
- •Документация mpl Последовательности
- •Концепции
- •(Прямая последовательность)
- •(Двунаправленная Последовательность)
- •(Последовательность произвольного доступа)
- •(Расширенная последовательность)
- •(Расширенная последовательность начала)
- •(Расширенная последовательность конца)
- •(Ассоциативная последовательность)
- •(Расширенная ассоциативная последовательность)
- •(Обертка интегральной последовательности )
- •(Переменная последовательность)
- •Представления
- •Метафункции (Внутренние)
- •Итераторы
- •Концепции
- •(Прямой итератор)
- •(Двунаправленный итератор)
- •(Итератор произвольного доступа)
- •Метафункции
- •Алгоритмы
- •Концепции
- •(Инсертер: механизм вставок)
- •Инсертеры (инсертер: механизм вставок)
- •Итеративные алгоритмы
- •Запрашиваемые алгоритмы
- •Преобразования
- •Метафункции
- •Концепции Метафункция
- •Метафункциональный класс
- •Лямбда выражения
- •Заполнители
- •Тэг диспетчеризированные метафункции
- •Числовые метафункции
- •Тривиальные метафункции
Указатели на функцию
Интегральные константы не единственные типы, значения которых вычисляются на этапе компиляции, значения следующих типов также могут быть вычислены во время компиляции:
Указатели и ссылки на определенный вид функций;
Указатели и ссылки на статические данные;
Указатели на «чистые» элементы: функции-класса;
Указатели на «чистые» элементы: переменные класса;
Используя эти типы в качестве параметров шаблона, можно добиться существенного повышения эффективности. Когда указатели объявлялись непосредственно в теле шаблонного класса, то его размер зависел от размера указателей, в случае, если они объявлены в списке параметров шаблона, размер указателей не влияет на размер класса:
template <class R, class F, F f, class G, G g> // Объявляем в списке параметров шаблона
struct compose_fg2
{
typedef R result_type;
template <class T>
R operator()(T const& x) const
{
return f(g(x));
}
};
Несмотря на то, что шаблон не содержит вложенных элементов, элементы из списка параметров могут использоваться в его теле, например для следующего расчета (sin2(log2(x))), который применяется к каждому элементу последовательности:
#include <functional>
#include <algorithm>
#include <cmath>
float input[5] = {0.0, 0.1, 0.2, 0.3, 0.4};
float output[5];
inline float log2(float x) { return std::log(x)/std::log(2); }
typedef float (*floatfun)(float);
float* ignored = std::transform(
input, input+5, output,
compose_fg2<float, floatfun, sin_squared, floatfun, log2>()
);
Дополнительный уровень косвенности посредством указателей, на большинстве компиляторов, не будет приводить к снижению эффективности вызовов, т.к. компилятор точно знает на какие функции ссылаются указатели f и g, в результате компилятор должен оптимизировать пустой объект compose_fg2, передаваемый в std::transform и осуществить прямые вызовы log2 и sin_squared.
Несмотря на все свои преимущества эффективности, compose_fg2 имеет ряд ограничений:
Поскольку значения тип класса не могут выступать в качестве значений шаблонных параметров, compose_fg2 не может принимать в качестве аргументов функторы.
Нет способа создавать объект посредством функции-генератора для автоматического вывода параметров шаблона compose_fg2. Объект генератор придется взять на себя функции, будет состоять в качестве аргументов функции и использовать эти значения в качестве аргументов compose_fg2 шаблон:
template <class R, class F, class G>
// Ошибка: не может определить тип возвращаемого значения из-за f и g.
compose_fg2<R,F,f,G,g> compose(F f, G g)
{
return compose_fg2<R,F,f,G,g>(); // error
}
Передача любого значения в функцию возможно только во время выполнения, потому вывести тип возвращаемого значения для функкции-генератора на этапе компиляции невозможно.
Ослабление типизации
Иногда полезно иметь возможность обходить статическую информацию о типе.
Например:
compose<float>(std::negate<float>(), &sin_squared)
с типом:
compose_fg<float,std::negate<float>,float(*)(float)>
std::bind2nd(std::multiplies<float>(), 3.14159)
с типом:
std::binder2nd<std::multiplies<float>>
Общий интерфейс, который позволяет осуществлять замещение вызовов обобщенных функций является классическим примером статического полиморфизма:
std::transform(
input, input+5, output,
compose<float>(std::negate<float>(), &sin_squared)
);
std::transform(
input, input+5, output,
std::bind2nd(std::multiplies<float>(), 3.14159)
);
Шаблонная функция не всегда являются лучшими обработчиками полиморфного поведения, особенно в следующих ситуациях:
Системы, структура которых может изменяться динамически (GUI) – требуют выполнения диспетчеризации на этапе выполнения.
Шаблонные функции не могут быть скомпилированы в объектный код и поставлены в библиотеках.
Каждый экземпляр шаблонной функции обычно приводит к новому машинному коду. Это может быть хорошо, когда функция очень мала, потому что код может быть встроен и локализован, в противном случае, программа может получиться больше, что может снизить ее эффективность.
