![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
InterfacingBoost , ,
Модульная конструкция Phoenix делает его чрезвычайно расширяемым. Мы видели, что слой за слоем, вся структура построена на прочном фундаменте. Есть только несколько простых хорошо продуманных концепций, которые выложены как кирпичи. В целом рамки предназначены для расширения. Все, что выше композита и примитивов, на самом деле может рассматриваться как расширение структуры. Этот модульный дизайн был унаследован отSpiritinline parser framework. Расширение не является навязчивым. И всякий раз, когда компонент или модуль расширяется, новое расширение автоматически становится гражданином первого класса и автоматически распознается всеми модулями и компонентами в рамках. Существует множество способов расширения модуля. 1) Написать и развернуть новый примитив: До сих пор мы представили лишь несколько примитивов 1) аргументов 2) значений и 3) переменных. Для иллюстрации напишем простое примитивное расширение. Назовем его static_int. Она должна быть параметризирована целым числом. Это похоже на статическую версию класса value
Вот так. Готово! Теперь мы можем использовать это, поскольку это уже полноценный гражданин Феникса из-за соответствия интерфейса. Давайте напишем подходящий генератор, чтобы было проще использовать наш static_int. Помните, что он должен быть обернут как актер, прежде чем его можно будет использовать. Назовем генератор int_const:
Теперь мы закончили. Давайте используем его:
Печатает "11". Есть много вещей, которые вы можете сделать с этой формой расширения. Например, на ум приходят типы данных. Пример:
2) Написать и развернуть новый состав: Это сложнее, чем наш первый пример (написание примитивного). Тем не менее, как только вы получите основы, написание композита будет почти механическим и скучным (читай: легко Ладно, давай продолжим. Вспомните, что ленивое утверждение if_ else (и все заявления на этот счет) возвращается в пустоту. Чего не хватает, и, безусловно, будет полезно, так это выражения C/C++ "cond ? a : b". Очень жаль, что C++ не допустил перегрузки. Вздох. В любом случае, вот код (образец 6.cpp):
Хорошо, это довольно много. Давайте переварим это по частям.
Это в основном специализированный композит, в котором 3 актера. Он не работает, поскольку подразумевается. 3 субъекта — cond (состояние типа CondT) true_ (истинная ветвь типа TrueT), false_ (ложная ветвь или тип FalseT).
self_t - это типдеф, который объявляет свой собственный тип: " Что это такое?"
Мы уже видели результат раньше. Для базовых классов актеров, таких как композиты и примитивы, параметром является TupleT, то есть искаженные аргументы, переданные от актера. Итак, учитывая некоторые аргументы, каким будет наш тип возвращения? «Ложь» и «Правда» — это то, что помнят актеры? Итак, во-первых, мы должны спросить их "Каковы ваши *простые* (без ссылок) типы возврата? "; Зная это, наша задача состоит в том, чтобы знать, какой тип имеет более высокий ранг (назовите ранг После этого, наконец, у нас есть тип возврата, типизированный по результату
Это наш конструктор. Мы просто вставляем аргументы конструктора в наши переменные.
Вот наша основная функция члена Эвал. Учитывая self_t, наш тип и TupleT, вычет типа возврата почти канонический. Просто спросите у актера результат, он наверняка узнает.
Мы передаем откачанные арги всем нашим актерам: конд, арг и арг соответственно. Обратите внимание, как это выражение отражает версию C/C++ почти до буквы. Вот и все. Теперь напишем генератор для этого композита:
Теперь это должно быть тривиально объяснить. Надеюсь. Опять же, давайте переварить этот фрагмент.
Опять же, есть три элемента: условие CondT «cond», истинная ветвь TrueT «true_» и ложная ветвь FalseT «false_».
Это наша цель. Мы хотим создать этого актера. Теперь, учитывая наши аргументы (cond, true_ и false_), мы не совсем уверены, действительно ли они актеры. Что делать, если пользователь передает булеву правду в виде конда? Конечно, это должно быть преобразовано в актера, иначе Феникс станет берзерком и не сможет принять этого инопланетянина.
Это именно то, что нам нужно. Этот тип компьютера преобразует из произвольного типа Т в полноценного действующего гражданина.
Таковы аргументы нашего генератора «if_else_».
Как и раньше, это наш целевой тип возвращения, на этот раз снятый с актера. Это нормально, потому что у актера есть конструктор, который принимает объект BaseT: результат в этом случае.
Наконец, мы создаем и возвращаем результат. Обратите внимание на то, как мы назвали статическую функцию as_actor Наконец-то. Теперь мы можем использовать наш новый композит и его генератор:
3) Написать преобразователь as_actor По умолчанию неизвестный тип T преобразуется в актера as_actor
Для справки, вот основной интерфейс_actor
Где??? Тип актора, возвращаемый статической преобразующей функцией. По умолчанию это:
4) Написать специализированного перегруженного оператора для конкретного типа: Рассмотрим обращение с оператором<< std::ostream, таким как cout. Когда мы видим такое выражение, как:
Перегрузка оператора фактически принимает кут по ссылке, изменяет его и возвращает тот же кут по ссылке. Это не соответствует стандартному поведению сменного левого оператора для встроенных интов. В таких случаях мы можем обеспечить специализированную перегрузку для работы в качестве ленивого оператора в таких выражениях, как "cout<< arg1<< arg2;", где оперативное поведение отклоняется от стандартного оператора:
Затем мы поставляем специальную перегрузку (см. Special_ops.hpp):
Обратите внимание, что эталон std::ostream преобразуется в actor Это еще не завершено. Обратите внимание также, что специализация для бинарных операторов также должна быть написана. 6). 5) Специализировать ранг Сценарий: У нас есть набор более специализированных цифровых классов с более высокой точностью, чем встроенные типы. У нас есть целые, плавающие и рациональные классы. Все классы позволяют создавать промо-акции из встроенных. Эти классы имеют все соответствующие операторы, реализованные вместе с несколькими операторами смешанного типа, когда это необходимо. Операторы соответствуют каноническому поведению встроенных типов. Мы хотим обеспечить поддержку Phoenix для наших цифровых классов. Решение: Напишите специализации ранга для наших цифровых типов. Это тривиально и просто:
Теперь, когда существуют операции смешанного типа, такие как a + b, где a — примитивный встроенный int, а b — наш рациональный класс, будет применено правильное продвижение, и результат будет рациональным. Тип с более высоким рангом победит. 6) Специализировать unary_operator Сценарий: У нас есть итератор, не соответствующий STL, называемый my_iterator. К счастью, его оператор ++ работает так, как и ожидалось. К сожалению, при применении оператора dereference *p он возвращает объект типа my_class, но не следует соглашению STL о том, что классы итераторов имеют обозначение typedef. Решение, напишите специализацию unary_operator для нашего нестандартного класса:
Сценарий: У нас есть устаревшая масштабная реализация, которую мы используем для криптографии. Дизайн класса полностью мертв и не подчиняется всем правилам. Например, его оператор + деструктивен и фактически применяет семантику += для эффективности (да, есть такие мертвые мозгом звери!). Решение: напишите специализацию binary_operator для нашего нестандартного класса:
Возвращаясь к нашему примеру в No 4, мы также должны написать бинарный_оператор
7) Просто напишите ленивую функцию. Подумайте об этом:
И это соответствующее использование:
Что такое $%?! Если мы можем сделать это, почему на земле мы пошли на все проблемы, закручивая наш мозг наизнанку с помощью композитного if_else в no. 2? Эй, не так быстро, есть небольшая разница, которая оправдывает композит if_else: Это не очевидно в примере, но составная версия if_else_ оценивает либо истинную, либо ложную ветвь, но не обе **. Приведенная выше версия с ленивой функцией всегда охотно оценивает все свои аргументы до того, как функция будет названа. Таким образом, если мы хотим строго придерживаться семантики C/C++, нам нужна композитная версия. Кроме того, мне нужно показать пример... Хммм, так в чем тогда смысл No7? Ну, в большинстве случаев ленивой функции будет достаточно. Эти звери довольно могущественны.
Copyright © 2001-2002 Joel de Guzman Статья Interfacing раздела может быть полезна для разработчиков на c++ и boost. Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта. :: Главная :: ::
|
|||||||||||||
©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007 |