![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
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.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
:: Главная :: ::
реклама |