![]() |
![]() ![]() ![]() ![]() |
![]() |
THE BOOST MPL LIBRARY: Higher-Order MetafunctionsBoost , ,
|
|||||||||
| Front Page / Tutorial: Metafunctions and Higher-Order Metaprogramming / Higher-Order Metafunctions |
В предыдущем разделе мы использовали две различные формы - классы метафункций и выражения заполнителей - для передачи и возврата метафункций, как и любые другие метаданные. Объединение метафункций в метаданные первого класса " позволяетПреобразованиевыполнять бесконечное множество различных операций: в нашем случае умножение и деление измерений. Хотя идея использования функций для манипулирования другими функциями может показаться простой, ее большая сила и гибкость могут быть очень простыми.[Худак89]Завоевал славное звание:Функциональное программирование более высокого порядка. Функция, которая работает на другой функции, известна как функцияболее высокого порядка. Из этого следует, чтотрансформируется.— метафункция более высокого порядка: метафункция, работающая на другой метафункции.
| [Hudak89] | Пол Худак. "Концепция, эволюция и применение языков функционального программирования," ACM Computing Surveys 21, no. 3 Pages: 359 - 411. Пресса. 1989. ISSN:0360-0300. http://doi.acm.org/10.1145/72551.72554. |
Теперь, когда мы увидели силу метафункций более высокого порядка, было бы хорошо иметь возможность создавать новые. Чтобы изучить основные механизмы, давайте попробуем простой пример. Наша задача состоит в том, чтобы написать метафункцию под названиемдважды, которая — при условии унарной метафункцииfи произвольных метаданныхx— вычисляет:
twice(f, x) := f(f(x))
Это может показаться тривиальным примером, и на самом деле это так. Вы не найдете много пользы длядваждыв реальном коде. Мы надеемся, что вы все равно будете с нами: Поскольку он не делает гораздо больше, чем принимает и вызывает метафункцию,дваждызахватывает все существенные элементы "высшего порядка" без каких-либо отвлекающих деталей.
Еслиfявляется классом метафункций, то определениедваждыпросто:
template <class F, class X>
struct twice
{
typedef typename F::template apply<X>::type once; // f(x)
typedef typename F::template apply<once>::type type; // f(f(x))
};
Или, применяя метафункцию пересылки:
template <class F, class X>
struct twice
: F::template apply<
typename F::template apply<X>::type
>
{};
C++ Language Note
Стандарт C++ требуетшаблонаключевого слова, когда мы используемзависимое имя, которое относится к шаблону участника.F::applyможет или не может назвать шаблон,в зависимостиот конкретногоF, который передается.См.Приложение В к книгеШаблон.
Учитывая необходимость посыпать наш код ключевым словомшаблон, было бы неплохо уменьшить синтаксическое бремя вызова классов метафункций. Как обычно, решение состоит в том, чтобы факторизировать шаблон в метафункцию:
template <class UnaryMetaFunctionClass, class Arg>
struct apply1
: UnaryMetaFunctionClass::template apply<Arg>
{};
дваждытолько:
template <class F, class X>
struct twice
: apply1<F, typename apply1<F,X>::type>
{};
Чтобы увидетьдваждына работе, мы можем применить его к немногому классу метафункций, построенному вокругadd_pointerметафункции:
struct add_pointer_f
{
template <class T>
struct apply : boost::add_pointer<T> {};
};
Теперь мы можем использоватьдваждысadd_pointer_fдля построения указателей на указатели:
BOOST_STATIC_ASSERT((
boost::is_same<
twice<add_pointer_f, int>::type
, int**
>::value
));
Статья THE BOOST MPL LIBRARY: Higher-Order Metafunctions раздела может быть полезна для разработчиков на c++ и boost.
:: Главная :: ::
реклама |