- •Вычисления значений
- •Пример:
- •Вычисления типов
- •Преимущества мета подхода:
- •Польза использования mpl:
- •Числовая метафункция
- •Свойства
- •Метаданные
- •Специализация
- •Первичный шаблон:
- •Инстанцирование:
- •Метафункции
- •Полиморфизм
- •Возможности свойств:
- •Организация свойств в Boost:
- •Пример:
- •Типовые ассоциации
- •Альтернатива:
- •Метафункции Продвижение (пересылка) метафункций
- •Класс метафункции
- •Формат:
- •Числовые
- •Пример:
- •Нульарные
- •Метрический анализ (Анализ размерностей)
- •Метрики
- •Величины
- •Сложение и вычитание
- •Умножение
- •Класс метафункции
- •Деление
- •Пример:
- •Метафункции высшего порядка (Каскады вложенных вызовов)
- •Использование apply:
- •Заполнители
- •Безымянный заполнитель:
- •Определение выражений с заполнителями
- •Лямбда (Лямбда метафункции/выражения)
- •Частичное приложение метафункции
- •Лямбда и Шаблоны Неметафункции
- •Обертки
- •Выбор типа
- •Ленивый Выбор Типа
- •Логические Операторы
- •Целочисленные обертки
- •Составные Операторы
- •Операторы с булевым значением:
- •Операторы для сравнения значений:
- •Операторы для интегральных значений:
- •Побитовые операторы:
- •Арифметические операторы:
- •Целочисленная «стенография»
- •Интегральные последовательности
- •Формат:
- •Последовательности
- •Концепции
- •Итераторы
- •Двунаправленные
- •Произвольные
- •Последовательности
- •Двунаправленные
- •Произвольные
- •Расширенные
- •Ассоциативные
- •Требования
- •Расширения
- •Расширенные ассоциативные последовательности
- •Алгоритмы и последовательности
- •Итераторы
- •Равенство
- •Операции Внутренние операции с последовательностей
- •Наследование
- •Создание последовательности
- •Реализация:
- •Создание итератора
- •Преимущества полной специализации перед частичной:
- •Добавление расширения
- •Алгоритмы
- •Абстракция:
- •Stl алгоритмы
- •Детали правильного использования stl:
- •Mpl алгоритмы
- •Различия stl и mpl алгоритмов:
- •Пример:
- •Вставки
- •Пример 1:
- •Пример 2:
- •Пример 3:
- •Фундамент алгоритмов
- •Пример:
- •Запрашиваемые алгоритмы
- •Последовательности (Алгоритмы, создающие последовательности)
- •Синонимы функциональных алгоритмов:
- •Создание алгоритма
- •Итераторы «Просмотр» и итераторы-адаптеры
- •Концепция просмотра
- •Применение просмотра Сравнения значений элементов последовательности:
- •Объединение множественных (мульти-) последовательностей
- •Упрощение 1
- •Упрощение 2 (создание просмотра)
- •Уход от ненужного вычисления
- •Выборочная обработка элемента
- •Итератор-адаптер
- •Создание просмотра
- •Реализация итератора-адаптера для zip_view.
- •Диагностика
- •Отладка ошибок
- •Трассировка инстанцирования
- •Исправленный пример:
- •Форматы сообщений об ошибках
- •Блок «with»
- •Устранение параметров шаблона по умолчанию
- •Глубокий typedef
- •Инструменты
- •Несколько компиляторов
- •(Статические Утверждения)
- •Формат:
- •Формат:
- •Индивидуальные сообщения утверждений
- •Настройка предиката:
- •(Генерирование встроенных сообщений)
- •Формат:
- •Выбор стратегии:
- •Тип печати
- •Кросс этапность компиляции/выполнения
- •Печать типов:
- •Тип посещения:
- •Выбор реализаций
- •Специализация шаблонов классов
- •Тег диспетчеризации
- •Выбор структуры
- •Композиция классов
- •Указатели на функцию
- •Ослабление типизации
- •Пример:
- •Обобщение:
- •Динамический полиморфизм
- •Автоматизация
- •Сохранение интерфейса
- •Рекуррентный шаблон
- •Формат:
- •Генерирование функций
- •Управление разрешением перегрузки
- •Явное управление множеством перегрузки
- •Документация mpl Последовательности
- •Концепции
- •(Прямая последовательность)
- •(Двунаправленная Последовательность)
- •(Последовательность произвольного доступа)
- •(Расширенная последовательность)
- •(Расширенная последовательность начала)
- •(Расширенная последовательность конца)
- •(Ассоциативная последовательность)
- •(Расширенная ассоциативная последовательность)
- •(Обертка интегральной последовательности )
- •(Переменная последовательность)
- •Представления
- •Метафункции (Внутренние)
- •Итераторы
- •Концепции
- •(Прямой итератор)
- •(Двунаправленный итератор)
- •(Итератор произвольного доступа)
- •Метафункции
- •Алгоритмы
- •Концепции
- •(Инсертер: механизм вставок)
- •Инсертеры (инсертер: механизм вставок)
- •Итеративные алгоритмы
- •Запрашиваемые алгоритмы
- •Преобразования
- •Метафункции
- •Концепции Метафункция
- •Метафункциональный класс
- •Лямбда выражения
- •Заполнители
- •Тэг диспетчеризированные метафункции
- •Числовые метафункции
- •Тривиальные метафункции
(Статические Утверждения)
Позволяют генерировать ошибку, когда обнаруживается неправильное использование кода:
BOOST_STATIC_ASSERT(integral-constant-expression);
Если выражение ложно (0), то выдается ошибка компиляции. Утверждения лучше всего использовать, чтобы убедиться, что предположения, при которых код был написан соответсвуют утверждению.
Пример метафункции расчета факториала:
template <class N>
struct factorial
: mpl::eval_if<
mpl::equal_to<N,mpl::int_<0>>, // check N == 0
mpl::int_<1>, // 0! == 1
mpl::multiplies< // N! == N * (N-1)!
N,
factorial<typename mpl::prior<N>::type>
>
>
{
BOOST_STATIC_ASSERT(N::value >= 0); // for nonnegative N
};
Вычисление факториала N! имеет смысл только при неотрицательном N, что и проверяет утверждение.
Если написать:
int const fact = factorial<mpl::int_<-6>>::value;
то получлим следующий дамп (Intel C++ 8.1):
foo.cpp(22): error: incomplete type is not allowed
BOOST_STATIC_ASSERT(N::value >= 0);
^
detected during instantiation of class "factorial<N>
[with N=mpl_::int_<-6>]" at line 25
Когда условие нарушается, то в сообщении об ошибке будеь указана строка, содержащая нарушенное утверждение. Т.о., мкрос BOOST_STATIC_ASSERT помогает компилятору разобраться в причинах ошибки.
Содержание диагностического сообщения выше вряд ли может быть более информативным: не только является источником линии отображаются, но мы видим, условия в вопросе и аргумент для факториала. В целом, однако, вы не можете полагаться на такие полезные результаты BOOST_STATIC_ASSERT. В этом случае мы получили их по более счастливой случайности, чем дизайн.
Многие компиляторы, в случае не срабатывания утверждения, не показывают строку с кодом утвреждения, в сообщении об ошибке (GCC 3.3.1):
foo.cpp: In instantiation of 'factorial<mpl_::int_<-6> >':
foo.cpp:25: instantiated from here
foo.cpp:22: error: invalid application of 'sizeof' to an
incomplete type
MPL предосталвяет набор макросов статических утверждений, цель которых, помочь компилятору генерировать более точные сообщения об ошибках.
BOOST_MPL_ASSERT
Формат:
BOOST_MPL_ASSERT((bool-valued-nullary-metafunction))
Обрати внимание на необходимость использования двойных скобок, даже если в условии не используются запятые.
Применим данный макрос к примеру с ошибочным использованием факториала:
#include <boost/mpl/greater_equal.hpp>
#include <boost/mpl/assert.hpp>
template <class N>
struct factorial
// ...
{
BOOST_MPL_ASSERT((mpl::greater_equal<N,mpl::int_<0>>));
};
Преимущество макроса BOOST_MPL_ASSERT в том, что имя его аргумента будет выведено в диагностике (GCC):
foo.cpp: In instantiation of 'factorial<mpl_::int_<-6> >':
foo.cpp:26: instantiated from here
foo.cpp:23: error: conversion from '
mpl_::failed**********boost::mpl::greater_equal<mpl_::int_<-6>,
mpl_::int_<0> >::***********' to non-scalar type '
mpl_::assert<false>' requested
foo.cpp:23: error: enumerator value for '
mpl_assertion_in_line_23' not integer constant
Нарушеные условия заключенны в последовательности звездочек.
BOOST_MPL_ASSERT на самом деле лучше подходит для проверки других видов условий. Например, мы могли бы попытаться обеспечить соблюдение соответствия N и интегральной константной обертки следующим образом:
BOOST_MPL_ASSERT((boost::is_integral<typename N::value_type>));
Чтобы запустить это утверждение, мы могли бы написать:
// attempt to make a "floating point constant wrapper"
struct five : mpl::int_<5> { typedef double value_type; }; // переопределим тип аргумента в обертке int_<5>.
int const fact = factorial<five>::value;
Диагностика:
...
foo.cpp:24: error: conversion from
'mpl_::failed************boost::is_integral<double>::************'
to non-scalar type 'mpl_::assert<false>' requested
...
BOOST_MPL_ASSERT_NOT
Чтобы проверять отрицательные условия с макросами BOOST_STATIC_ASSERT или BOOST_MPL_ASSERT, необходимо использовать обертку-предикат mpl::not_<...>.
Чтобы упростить отрицательные утверждения, MPL предоставляет маркос BOOST_MPL_ASSERT_NOT, который применяет данную обертку неявно.
Применение:
BOOST_MPL_ASSERT_NOT((mpl::less<N,mpl::int_<0>>));
То, что за макросом стоит обертка видно из сообщения об ошибке:
foo.cpp:24: error: conversion from 'mpl_::failed
************boost::mpl::not_<boost::mpl::less<mpl_::int_<-5>,
mpl_::int_<0> > >::************' to non-scalar type
'mpl_::assert<false>' requested
BOOST_MPL_ASSERT_RELATION
BOOST_MPL_ASSERT не очень хорошо подходит для проверки численных условий, поскольку диагностика и утверждения сопряжены и так с большими синтаксическими накладными расходами. Написание mpl::greater_equal <x,y>, для проверки, что х >= у, не выполняется, в общем случае, напрямую. Для такого рода численных сравнений, MPL предоставляет специализированный макрос.
