- •Вычисления значений
- •Пример:
- •Вычисления типов
- •Преимущества мета подхода:
- •Польза использования mpl:
- •Числовая метафункция
- •Свойства
- •Метаданные
- •Специализация
- •Первичный шаблон:
- •Инстанцирование:
- •Метафункции
- •Полиморфизм
- •Возможности свойств:
- •Организация свойств в Boost:
- •Пример:
- •Типовые ассоциации
- •Альтернатива:
- •Метафункции Продвижение (пересылка) метафункций
- •Класс метафункции
- •Формат:
- •Числовые
- •Пример:
- •Нульарные
- •Метрический анализ (Анализ размерностей)
- •Метрики
- •Величины
- •Сложение и вычитание
- •Умножение
- •Класс метафункции
- •Деление
- •Пример:
- •Метафункции высшего порядка (Каскады вложенных вызовов)
- •Использование apply:
- •Заполнители
- •Безымянный заполнитель:
- •Определение выражений с заполнителями
- •Лямбда (Лямбда метафункции/выражения)
- •Частичное приложение метафункции
- •Лямбда и Шаблоны Неметафункции
- •Обертки
- •Выбор типа
- •Ленивый Выбор Типа
- •Логические Операторы
- •Целочисленные обертки
- •Составные Операторы
- •Операторы с булевым значением:
- •Операторы для сравнения значений:
- •Операторы для интегральных значений:
- •Побитовые операторы:
- •Арифметические операторы:
- •Целочисленная «стенография»
- •Интегральные последовательности
- •Формат:
- •Последовательности
- •Концепции
- •Итераторы
- •Двунаправленные
- •Произвольные
- •Последовательности
- •Двунаправленные
- •Произвольные
- •Расширенные
- •Ассоциативные
- •Требования
- •Расширения
- •Расширенные ассоциативные последовательности
- •Алгоритмы и последовательности
- •Итераторы
- •Равенство
- •Операции Внутренние операции с последовательностей
- •Наследование
- •Создание последовательности
- •Реализация:
- •Создание итератора
- •Преимущества полной специализации перед частичной:
- •Добавление расширения
- •Алгоритмы
- •Абстракция:
- •Stl алгоритмы
- •Детали правильного использования stl:
- •Mpl алгоритмы
- •Различия stl и mpl алгоритмов:
- •Пример:
- •Вставки
- •Пример 1:
- •Пример 2:
- •Пример 3:
- •Фундамент алгоритмов
- •Пример:
- •Запрашиваемые алгоритмы
- •Последовательности (Алгоритмы, создающие последовательности)
- •Синонимы функциональных алгоритмов:
- •Создание алгоритма
- •Итераторы «Просмотр» и итераторы-адаптеры
- •Концепция просмотра
- •Применение просмотра Сравнения значений элементов последовательности:
- •Объединение множественных (мульти-) последовательностей
- •Упрощение 1
- •Упрощение 2 (создание просмотра)
- •Уход от ненужного вычисления
- •Выборочная обработка элемента
- •Итератор-адаптер
- •Создание просмотра
- •Реализация итератора-адаптера для zip_view.
- •Диагностика
- •Отладка ошибок
- •Трассировка инстанцирования
- •Исправленный пример:
- •Форматы сообщений об ошибках
- •Блок «with»
- •Устранение параметров шаблона по умолчанию
- •Глубокий typedef
- •Инструменты
- •Несколько компиляторов
- •(Статические Утверждения)
- •Формат:
- •Формат:
- •Индивидуальные сообщения утверждений
- •Настройка предиката:
- •(Генерирование встроенных сообщений)
- •Формат:
- •Выбор стратегии:
- •Тип печати
- •Кросс этапность компиляции/выполнения
- •Печать типов:
- •Тип посещения:
- •Выбор реализаций
- •Специализация шаблонов классов
- •Тег диспетчеризации
- •Выбор структуры
- •Композиция классов
- •Указатели на функцию
- •Ослабление типизации
- •Пример:
- •Обобщение:
- •Динамический полиморфизм
- •Автоматизация
- •Сохранение интерфейса
- •Рекуррентный шаблон
- •Формат:
- •Генерирование функций
- •Управление разрешением перегрузки
- •Явное управление множеством перегрузки
- •Документация mpl Последовательности
- •Концепции
- •(Прямая последовательность)
- •(Двунаправленная Последовательность)
- •(Последовательность произвольного доступа)
- •(Расширенная последовательность)
- •(Расширенная последовательность начала)
- •(Расширенная последовательность конца)
- •(Ассоциативная последовательность)
- •(Расширенная ассоциативная последовательность)
- •(Обертка интегральной последовательности )
- •(Переменная последовательность)
- •Представления
- •Метафункции (Внутренние)
- •Итераторы
- •Концепции
- •(Прямой итератор)
- •(Двунаправленный итератор)
- •(Итератор произвольного доступа)
- •Метафункции
- •Алгоритмы
- •Концепции
- •(Инсертер: механизм вставок)
- •Инсертеры (инсертер: механизм вставок)
- •Итеративные алгоритмы
- •Запрашиваемые алгоритмы
- •Преобразования
- •Метафункции
- •Концепции Метафункция
- •Метафункциональный класс
- •Лямбда выражения
- •Заполнители
- •Тэг диспетчеризированные метафункции
- •Числовые метафункции
- •Тривиальные метафункции
Пример:
//+--------------------------------------------------------------------+
// Задание 1:
template<class T> struct add_const_ref
{
typedef const T & type;
};
//Задание 2:
template<class T1, class T2, class T3> struct replace_type
{
typedef T3 type;
};
template<class T1, class T2> struct replace_type<T1*, T1, T2>
{
typedef T2* type;
};
template<class T1, class T2, size_t N> struct replace_type<T1 const*[N], const T1, T2>
{
typedef const T2*(*type)[N];
};
template<class T1, class T2> struct replace_type<T1(*)(T1), T1, T2>
{
typedef T2(*type)(T2) ;
};
int main()
{
// Задание 1:
cout << typeid(add_const_ref<int>::type).name() << endl;
// Задание 2:
typedef replace_type< void*, void, int >::type t1; // int*
cout << typeid(t1).name() << endl;
typedef replace_type<
int const*[10]
, int const
, long
>::type t2; // long* [10]
cout << typeid(t2).name() << endl;
typedef replace_type<
char& (*)(char&)
, char&
, long&
>::type t3; // long& (*)(long&)
cout << typeid(t3).name() << endl;
// Задание 3:
return 0;
}
Типовые ассоциации
Все метаданные можно разделить на две категории: типы и нетипы (значения). Оба вида метаданных могут использоваться в качестве шаблонных параметров.
Рассмотрим алгоритм работы с типами iter_swap:
В класическом варианте данный алгоритм принимает два итератора и меняет значения объектов, к которым они обращаются:
template <class ForwardIterator1, class ForwardIterator2>
void iter_swap(ForwardIterator1 i1, ForwardIterator2 i2)
{
T tmp = *i1;
*i1 = *i2;
*i2 = tmp;
}
«T» - тип, но в такой записи он не будет распознан и это приведет к ошибке компиляции. Необходимо объяснить компилятору, что работа ведется с типом.
Решение:
Если бы мы выбирали метод обработки итераторов для написания различных алгоритмов, многие из которых должны будут сделать ассоциацию между типом итератора и типом его значения. Мы могли бы потребовать, чтобы все итераторы содержали вложенный тип, названный value_type, к которому мы бы получали доступ непосредственно:
template <class ForwardIterator1, class ForwardIterator2>
void iter_swap(ForwardIterator1 i1, ForwardIterator2 i2)
{
typename ForwardIterator1::value_type tmp = *i1;
*i1 = *i2;
*i2 = tmp;
}
*Стандарт C++ требует ключевого слова typename, когда используется зависимое имя (с помощью «::») для обращения к типу.
Это хорошая стратегия создания ассоциаций типа, но она не является обобщенной. В частности итераторы в C++ смоделированы на примере указателей, с намерением, что простые указатели вели себя эквивалентно итераторам. Проблема в том, что у указателей не может быть вложенных типов; это доступно только классам:
void f(int* p1, int* p2)
{
iter_swap(p1,p2); // error: int* has no member 'value_type'
}
Решение: введение дополнительного уровня абстракции – теорема FTSE.
Согласно этой теореме, мы, возможно, не в состоянии добавить вложенный «:: value_type» ко всем итераторам, но мы можем добавить это к шаблону, который принимает тип итератора в качестве параметра – это и будет дополнительная абстракция, решающая проблему.
В стандартной библиотеке этот шаблон, назвывается iterator_traits:
template <class Iterator> struct iterator_traits;
Применим эту идею к алгоритму iter_swap:
template <class ForwardIterator1, class ForwardIterator2>
void iter_swap(ForwardIterator1 i1, ForwardIterator2 i2)
{
typename
iterator_traits<ForwardIterator1>::value_type tmp = *i1;
*i1 = *i2;
*i2 = tmp;
}
Шаблон iterator_traits описвает пять свойств для типа:
value_type;
reference;
pointer;
difference_type;
iterator_category;
Наибольшая польза iterator_traits: они дают нам способ связать информацию с типом.
Например: ваш злобный коллега, Гектор дает вам некоторый тип подобный iterator, названный hands_off, который обращается к интервалу, можно обратится к его value_type, не нарушая гармонии рабочей группы. Все, что необходимо сделать -добавить частичную специализация iterator_traits, и iter_swap будет видеть интервал типа, посредством value_type для итератора Гектора:
namespace std
{
template <>
struct iterator_traits<Hector::hands_off>
{
typedef int value_type;
//four more typedefs...
};
}
стандартная библиотека содержит следующую частичную специализацию iterator_traits, который описывает value_type всех указателей:
template <class T>
struct iterator_traits<T*>
{
typedef T value_type;
//...four more typedefs
};
Благодаря косвенности через iterator_traits обобщенные функции могут получить доступ ассоциированным типам однородно, независимот от того является ли тип указателем.
