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

Величины

Упомянутые выше типы являются все еще чистыми метаданными; типовая проверка реальных вычислений нуждается в данных времени выполнения.

Решение: использование оберток для числовых значений с дополнительным параметром Т для установки размерности - позволит выразить размерности как отдельный тип (привносит статическую типизацию), с внутренним состоянием:

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++ препроцессор не может разобрать шаблоны.

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