- •Вычисления значений
- •Пример:
- •Вычисления типов
- •Преимущества мета подхода:
- •Польза использования mpl:
- •Числовая метафункция
- •Свойства
- •Метаданные
- •Специализация
- •Первичный шаблон:
- •Инстанцирование:
- •Метафункции
- •Полиморфизм
- •Возможности свойств:
- •Организация свойств в Boost:
- •Пример:
- •Типовые ассоциации
- •Альтернатива:
- •Метафункции Продвижение (пересылка) метафункций
- •Класс метафункции
- •Формат:
- •Числовые
- •Пример:
- •Нульарные
- •Метрический анализ (Анализ размерностей)
- •Метрики
- •Величины
- •Сложение и вычитание
- •Умножение
- •Класс метафункции
- •Деление
- •Пример:
- •Метафункции высшего порядка (Каскады вложенных вызовов)
- •Использование apply:
- •Заполнители
- •Безымянный заполнитель:
- •Определение выражений с заполнителями
- •Лямбда (Лямбда метафункции/выражения)
- •Частичное приложение метафункции
- •Лямбда и Шаблоны Неметафункции
- •Обертки
- •Выбор типа
- •Ленивый Выбор Типа
- •Логические Операторы
- •Целочисленные обертки
- •Составные Операторы
- •Операторы с булевым значением:
- •Операторы для сравнения значений:
- •Операторы для интегральных значений:
- •Побитовые операторы:
- •Арифметические операторы:
- •Целочисленная «стенография»
- •Интегральные последовательности
- •Формат:
- •Последовательности
- •Концепции
- •Итераторы
- •Двунаправленные
- •Произвольные
- •Последовательности
- •Двунаправленные
- •Произвольные
- •Расширенные
- •Ассоциативные
- •Требования
- •Расширения
- •Расширенные ассоциативные последовательности
- •Алгоритмы и последовательности
- •Итераторы
- •Равенство
- •Операции Внутренние операции с последовательностей
- •Наследование
- •Создание последовательности
- •Реализация:
- •Создание итератора
- •Преимущества полной специализации перед частичной:
- •Добавление расширения
- •Алгоритмы
- •Абстракция:
- •Stl алгоритмы
- •Детали правильного использования stl:
- •Mpl алгоритмы
- •Различия stl и mpl алгоритмов:
- •Пример:
- •Вставки
- •Пример 1:
- •Пример 2:
- •Пример 3:
- •Фундамент алгоритмов
- •Пример:
- •Запрашиваемые алгоритмы
- •Последовательности (Алгоритмы, создающие последовательности)
- •Синонимы функциональных алгоритмов:
- •Создание алгоритма
- •Итераторы «Просмотр» и итераторы-адаптеры
- •Концепция просмотра
- •Применение просмотра Сравнения значений элементов последовательности:
- •Объединение множественных (мульти-) последовательностей
- •Упрощение 1
- •Упрощение 2 (создание просмотра)
- •Уход от ненужного вычисления
- •Выборочная обработка элемента
- •Итератор-адаптер
- •Создание просмотра
- •Реализация итератора-адаптера для zip_view.
- •Диагностика
- •Отладка ошибок
- •Трассировка инстанцирования
- •Исправленный пример:
- •Форматы сообщений об ошибках
- •Блок «with»
- •Устранение параметров шаблона по умолчанию
- •Глубокий typedef
- •Инструменты
- •Несколько компиляторов
- •(Статические Утверждения)
- •Формат:
- •Формат:
- •Индивидуальные сообщения утверждений
- •Настройка предиката:
- •(Генерирование встроенных сообщений)
- •Формат:
- •Выбор стратегии:
- •Тип печати
- •Кросс этапность компиляции/выполнения
- •Печать типов:
- •Тип посещения:
- •Выбор реализаций
- •Специализация шаблонов классов
- •Тег диспетчеризации
- •Выбор структуры
- •Композиция классов
- •Указатели на функцию
- •Ослабление типизации
- •Пример:
- •Обобщение:
- •Динамический полиморфизм
- •Автоматизация
- •Сохранение интерфейса
- •Рекуррентный шаблон
- •Формат:
- •Генерирование функций
- •Управление разрешением перегрузки
- •Явное управление множеством перегрузки
- •Документация mpl Последовательности
- •Концепции
- •(Прямая последовательность)
- •(Двунаправленная Последовательность)
- •(Последовательность произвольного доступа)
- •(Расширенная последовательность)
- •(Расширенная последовательность начала)
- •(Расширенная последовательность конца)
- •(Ассоциативная последовательность)
- •(Расширенная ассоциативная последовательность)
- •(Обертка интегральной последовательности )
- •(Переменная последовательность)
- •Представления
- •Метафункции (Внутренние)
- •Итераторы
- •Концепции
- •(Прямой итератор)
- •(Двунаправленный итератор)
- •(Итератор произвольного доступа)
- •Метафункции
- •Алгоритмы
- •Концепции
- •(Инсертер: механизм вставок)
- •Инсертеры (инсертер: механизм вставок)
- •Итеративные алгоритмы
- •Запрашиваемые алгоритмы
- •Преобразования
- •Метафункции
- •Концепции Метафункция
- •Метафункциональный класс
- •Лямбда выражения
- •Заполнители
- •Тэг диспетчеризированные метафункции
- •Числовые метафункции
- •Тривиальные метафункции
Композиция классов
Используя технику выбора структуры класса, можно реализовать мехнизм более гибкой сборки классов из отдельных мелких модулей.
Например, генерирование структуры класса, но основе последовательности типов. Для раскрутки последовательности применим алгоритм fold:
// fine-grained struct element; stores a T and inherits More
template <class T, class More>
struct store : More
{
T value;
};
typedef mpl::vector<short[2], long, char*, int> member_types;
struct empty {};
mpl::fold<
member_types, empty, store<_2,_1>
>::type generated;
Сгенерированная структура типов имеет следующий вид:
store<int,
store<char*,
store<long,
store<short[2], empty>
>
>
>
Каждая специализация store, представляет собой отдельный уровень в сгенерированной иерархии наследования, инциализированный отдельным типом из списка member_types.
Использование комползиции классов таким образом может быть затруднительно если они недостаточно структурированы. Сложность состоит в доступе к каждому отдельному типу, т.к. все имеют идентичное имя «::value» с разной степень вложенности. (Для организации такого доступа можно использовать метапрограммирование препроцессора.)
Более того, трудно получить доступ к значению элемента данного типа трудно, даже с помощью приведения к соответствующему базовому классу:
long& x = static_cast<store<long, store<short[2], empty>>&>(generated).value;
Другими словами, доступ к любому элементу иерархии store требует знания всех типов после запрашиваемого типа в исходной последовательности. Можно применитьбы специальную функцию для автоматического вывода аргументов, чтоб компилятор сам определял цепь базовых классов:
template <class T, class U>
store<T, U> const& get(store<T, U> const& e)
{
return e;
}
char* s = get<char*>(generated).value;
В приведенном выше примере, первый шаблонный параметр будет инициализирован типом char*, а действительный параметр функции shore<char*,U> const&, который соответствует базовому классу, содержащему сгенерированный элемент типа char*.
Упростим данное решение, добавив дополнительный уровень абстракции (Фундаментальная Теорема Программирования).
// fine-grained struct element; wraps a T
template <class T>
struct wrap
{
T value;
};
// one more level of indirection
template <class U, class V>
struct inherit : U, V
{};
typedef mpl::vector<short[2], long, char*, int> member_types;
struct empty {};
mpl::fold<
member_types, empty, inherit<wrap<_2>,_1>
>::type generated;
Сгенерированная структура типов имеет следующий вид:
inherit<wrap<int>,
inherit<wrap<char*>,
inherit<wrap<long>,
inherit<wrap<short[2]>,
empty
>
>
>
>
Т.к. inherit<U,V> наследует оба класса U и V, то для каждого типа из списка будет создан индивидуальный базовый класс (без хвоста типов), что позволит проще получить к нему доступ:
long& x = static_cast<wrap<long> &>(generated).value;
Генерирование классов таким образом является фундаментальной метапрограммной деятельностью, поэтому MPL предоставляет готовые средства для решения подобных задач. В частности, можно заменить empty и inherit на mpl::empty_base и mpl::inherit. Библиотека также содержит соответствующую метафункцию inherit_linearly, которая вызывает fold с типом параметра по умолчанию mpl::empty_base:
template <class Types, class Node, class Root = empty_base>
struct inherit_linearly
: fold<Types,Root,Node>
{};
С использованием данных инструментов можно реализовать генерацию классовой иерархии и обеспечение доступа к элементам в более удобной форме:
#include <boost/mpl/inherit.hpp>
#include <boost/mpl/inherit_linearly.hpp>
#include <boost/mpl/vector.hpp>
// fine-grained struct element
template <class T>
struct wrap
{
T value;
};
typedef mpl::vector<short[2], long, char*, int> member_types;
mpl::inherit_linearly<
member_types, mpl::inherit<wrap<_2>,_1>
>::type generated;
int main()
{
long& x = static_cast<wrap<long>&>(generated).value;
cout << x << endl;
return 0;
}
Эти механизмы были подробно исследованы Андреем Александреску. Например, им используется композиция классов для генерации посетителей для обобщенного множественного выбора сред.
