Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
template_metaprogramming_ru.docx
Скачиваний:
12
Добавлен:
01.07.2025
Размер:
774 Кб
Скачать
☆

Алгоритмы и последовательности

Основное назначение алгоритмов в MPL – манипуляции последовательностями.

Например, поиск типа в векторе:

typedef mpl::vector<char,short,int,long,float,double> types;

// locate the position of long in types

typedef mpl::find<types, long>::type long_pos;

Так, сопоставляются каждый тип последовательности и заданный тип long, а возвращается итератор указывающий на индекс элемента равный заданному типу. Особенность в том, что последовательность передается 1 аргументом, а не двумя граничными итераторами как в STL:

std::vector<int> x(10);

std::vector<int>::iterator five_pos = std::find(x.begin(), x.end(), 5);

Если сопоставление не найдено, то алгоритм возвращает последний итератор последовательности:

// assert that long was found in the sequence

typedef mpl::end<types>::type finish;

BOOST_STATIC_ASSERT((!boost::is_same<long_pos, finish>::value));

Также существет метафункция begin, которая возвразщает итератор начала последовательности.

Итераторы

Итераторы – абстракция указателя для доступа к элементам последовательностей. Из-за того, что итераторы в MPL работают на этапе компиляции к ним нельзя применять оператор «*», перегрузка данного оператора просто недоступна во время компиляции. Вместо этого MPL предоставляет метафункцию deref, которая раскрывает содержимое иетартора.

typedef mpl::vector<char,short,int,long,float,double> types;

// locate the position of long in types

typedef mpl::find<types,long>::type long_pos; // тип итератора, который содержит индекс типа long или end

// dereference the iterator

typedef mpl::deref<long_pos>::type x;

// check that we have the expected result

BOOST_STATIC_ASSERT((boost::is_same<x,long>::value));

Итератор может также обеспечить доступ к смежным элементам в последовательности, или выполнить обход по остальным. Примитивы mpl::next и mpl::prior применимы и к итераторам.

typedef mpl::next<long_pos>::type float_pos;

BOOST_STATIC_ASSERT

((

boost::is_same<

mpl::deref<float_pos>::type

, float

>::value

));

Равенство

Равенство последовательностей важный момент, особенно при сравнении результатов вычислений, что позвоялет ошибочной идентичности.

Например, не нужно ожидать, чтобы следующее утверждение было выполнено:

BOOST_STATIC_ASSERT(( // error

boost::is_same<

mpl::pop_back<mpl::vector<int, short>>::type

, mpl::vector<int>

>::value

));

В большинстве случаев два типа, сравниваемые выше, будут действовать одинаково. Тем не менее, результат использования mpl::pop_back и специализации mpl::вектор не будут равными.

Шаблонная функция, которая может быть вызвана с двумя идентичными типами, вероятно не будет работать как ожидалось, если эти типы - последовательности. То же самое относится и к шаблонному классу, частичная специализация приведет к равенству последовательностей только когда два аргумента типа идентичны.

Правильный способ проверить на равенство последовательности состоит в том, чтобы всегда использовать алгоритм equal, следующим образом:

BOOST_STATIC_ASSERT(( // OK

mpl::equal<

mpl::pop_back<mpl::vector<int, short>>::type

, mpl::vector<int>

>::value

));

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]