- •Вычисления значений
- •Пример:
- •Вычисления типов
- •Преимущества мета подхода:
- •Польза использования mpl:
- •Числовая метафункция
- •Свойства
- •Метаданные
- •Специализация
- •Первичный шаблон:
- •Инстанцирование:
- •Метафункции
- •Полиморфизм
- •Возможности свойств:
- •Организация свойств в Boost:
- •Пример:
- •Типовые ассоциации
- •Альтернатива:
- •Метафункции Продвижение (пересылка) метафункций
- •Класс метафункции
- •Формат:
- •Числовые
- •Пример:
- •Нульарные
- •Метрический анализ (Анализ размерностей)
- •Метрики
- •Величины
- •Сложение и вычитание
- •Умножение
- •Класс метафункции
- •Деление
- •Пример:
- •Метафункции высшего порядка (Каскады вложенных вызовов)
- •Использование apply:
- •Заполнители
- •Безымянный заполнитель:
- •Определение выражений с заполнителями
- •Лямбда (Лямбда метафункции/выражения)
- •Частичное приложение метафункции
- •Лямбда и Шаблоны Неметафункции
- •Обертки
- •Выбор типа
- •Ленивый Выбор Типа
- •Логические Операторы
- •Целочисленные обертки
- •Составные Операторы
- •Операторы с булевым значением:
- •Операторы для сравнения значений:
- •Операторы для интегральных значений:
- •Побитовые операторы:
- •Арифметические операторы:
- •Целочисленная «стенография»
- •Интегральные последовательности
- •Формат:
- •Последовательности
- •Концепции
- •Итераторы
- •Двунаправленные
- •Произвольные
- •Последовательности
- •Двунаправленные
- •Произвольные
- •Расширенные
- •Ассоциативные
- •Требования
- •Расширения
- •Расширенные ассоциативные последовательности
- •Алгоритмы и последовательности
- •Итераторы
- •Равенство
- •Операции Внутренние операции с последовательностей
- •Наследование
- •Создание последовательности
- •Реализация:
- •Создание итератора
- •Преимущества полной специализации перед частичной:
- •Добавление расширения
- •Алгоритмы
- •Абстракция:
- •Stl алгоритмы
- •Детали правильного использования stl:
- •Mpl алгоритмы
- •Различия stl и mpl алгоритмов:
- •Пример:
- •Вставки
- •Пример 1:
- •Пример 2:
- •Пример 3:
- •Фундамент алгоритмов
- •Пример:
- •Запрашиваемые алгоритмы
- •Последовательности (Алгоритмы, создающие последовательности)
- •Синонимы функциональных алгоритмов:
- •Создание алгоритма
- •Итераторы «Просмотр» и итераторы-адаптеры
- •Концепция просмотра
- •Применение просмотра Сравнения значений элементов последовательности:
- •Объединение множественных (мульти-) последовательностей
- •Упрощение 1
- •Упрощение 2 (создание просмотра)
- •Уход от ненужного вычисления
- •Выборочная обработка элемента
- •Итератор-адаптер
- •Создание просмотра
- •Реализация итератора-адаптера для zip_view.
- •Диагностика
- •Отладка ошибок
- •Трассировка инстанцирования
- •Исправленный пример:
- •Форматы сообщений об ошибках
- •Блок «with»
- •Устранение параметров шаблона по умолчанию
- •Глубокий typedef
- •Инструменты
- •Несколько компиляторов
- •(Статические Утверждения)
- •Формат:
- •Формат:
- •Индивидуальные сообщения утверждений
- •Настройка предиката:
- •(Генерирование встроенных сообщений)
- •Формат:
- •Выбор стратегии:
- •Тип печати
- •Кросс этапность компиляции/выполнения
- •Печать типов:
- •Тип посещения:
- •Выбор реализаций
- •Специализация шаблонов классов
- •Тег диспетчеризации
- •Выбор структуры
- •Композиция классов
- •Указатели на функцию
- •Ослабление типизации
- •Пример:
- •Обобщение:
- •Динамический полиморфизм
- •Автоматизация
- •Сохранение интерфейса
- •Рекуррентный шаблон
- •Формат:
- •Генерирование функций
- •Управление разрешением перегрузки
- •Явное управление множеством перегрузки
- •Документация mpl Последовательности
- •Концепции
- •(Прямая последовательность)
- •(Двунаправленная Последовательность)
- •(Последовательность произвольного доступа)
- •(Расширенная последовательность)
- •(Расширенная последовательность начала)
- •(Расширенная последовательность конца)
- •(Ассоциативная последовательность)
- •(Расширенная ассоциативная последовательность)
- •(Обертка интегральной последовательности )
- •(Переменная последовательность)
- •Представления
- •Метафункции (Внутренние)
- •Итераторы
- •Концепции
- •(Прямой итератор)
- •(Двунаправленный итератор)
- •(Итератор произвольного доступа)
- •Метафункции
- •Алгоритмы
- •Концепции
- •(Инсертер: механизм вставок)
- •Инсертеры (инсертер: механизм вставок)
- •Итеративные алгоритмы
- •Запрашиваемые алгоритмы
- •Преобразования
- •Метафункции
- •Концепции Метафункция
- •Метафункциональный класс
- •Лямбда выражения
- •Заполнители
- •Тэг диспетчеризированные метафункции
- •Числовые метафункции
- •Тривиальные метафункции
Величины
Упомянутые выше типы являются все еще чистыми метаданными; типовая проверка реальных вычислений нуждается в данных времени выполнения.
Решение: использование оберток для числовых значений с дополнительным параметром Т для установки размерности - позволит выразить размерности как отдельный тип (привносит статическую типизацию), с внутренним состоянием:
template <class T, class Dimensions>
struct quantity
{
explicit quantity(T x) : m_value(x){}
T value() const { return m_value; }
private:
T m_value;
};
Теперь есть способ связать конкретные числа с размерностями:
quantity<float, length> l( 1.0f );
quantity<float, mass> m( 2.0f );
Размерности больше не появляются нигде в определении величины вне шаблонного списка параметров; единственная цель такого параметра – гарантировать отличие типов для l и м. Поскольку образовалась строгая типизация для размерностей, то попытка присвоить данные одной размерности другой приведут к ошибке компиляции:
m = l; // compile time type error
Сложение и вычитание
Теперь можно записать правила для сложений и вычитаний, так как типы размерностей должны всегда соответствовать друг другу.
template <class T, class D>
quantity<T,D> operator + (quantity<T,D> x, quantity<T,D> y)
{
return quantity<T, D>(x.value() + y.value());
}
template <class T, class D>
quantity<T,D> operator - (quantity<T,D> x, quantity<T,D> y)
{
return quantity<T, D>(x.value() - y.value());
}
*Так динамика (операции этапа ваполнения) строго регламентируются статикой (этап компиляции), что позволяет определять необходимые проверки и предотвращает нарушение динамикой логики, заложенной на статичном уровне.
Эти операторы позволяют записать следующее:
quantity<float,length> len1( 1.0f );
quantity<float,length> len2( 2.0f );
len1 = len1 + len2; // OK
и предотвращает использование в выражении другой размерности:
len1 = len2 + quantity<float, mass>( 3.7f ); // error: попытка сложения массы и длины
Умножение
Умножение является немного более сложным чем сложение и вычитание. До сих пор размерности аргументов и результатов вычисления были идентичны, но при умножении могут возникать другие размерности.
Умножение величин разной размерности имеет вид:
(xa) * (xb) = (xa+b);
Так, показатели степени аргументов должны складываться, а результат должен становится элементом новой последовательности (новая размерность – последовательность новых элемнтов). Чтобы объединить соответствующие элементы двух последовательностей применим статический алгоритм преобразования – transform. Transform - метафункция, которая осуществялет проход по двум последовательностям параллельно, передавая элементы каждой последовательности в некоторую отдельную метафункцию (обработчик), и помещая результат в выходную последовательность.
template <class Sequence1, class Sequence2, class BinaryOperation>
struct transform; // returns a Sequence
Формат алгоритма mpl::transform эквивалентен алгоритму из STL:
template
<
class InputIterator1, // начало первой последовательности
class InputIterator2, // конец первой последовательности
class OutputIterator, // начало второй последовательности
class BinaryOperation // обработчик
>
void transform(
InputIterator1 start1,
InputIterator1 finish1,
InputIterator2 start2,
OutputIterator result,
BinaryOperation func
);
Теперь необходимо передать соответствующую BinaryOperation, которая будет складывать/вычитать показатели степени для каждого элемента последовательностей. В MPL для подобных задач есть специальные метафункции plus и minus:
#include <boost/static_assert.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/int.hpp>
namespace mpl = boost::mpl;
BOOST_STATIC_ASSERT
(
(
mpl::plus<mpl::int_<2>, mpl::int_<3>>::type::value == 5
)
);
BOOST_STATIC_ASSERT: макрос, который вызывает ошибку компиляции, если ее аргумент ложен. Двойные круглые скобки требуются, потому что C++ препроцессор не может разобрать шаблоны.
