Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Boost.Flyweight Documentation - Tutorial - Extending Boost.Flyweight

Boost , , Boost.Flyweight Documentation - Tutorial

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

Boost.Flyweight Tutorial: Extending Boost.Flyweight



Contents

Introduction

Повышаю. Flyweight предоставляет спецификации публичного интерфейса для своихконфигурируемых аспектов.чтобы пользователь мог расширить библиотеку, реализовав собственные компоненты и предоставив их для инстанциаций шаблона класса<flyweight>.

В большинстве случаев существуют два типа сущностей, участвующих в расширении данного аспекта. Вес:

  • Сам компонент (император, шаблон фабричного класса).
  • ,,,< [10] >,< [10] >,< [10] >,< [10] >.
Например, тип<static_holder>является спецификатором держателя, который используется<flyweight>для генерации фактических классов держателя, в этом случае инстанциации шаблона класса.<static_holder_class>. Обратите внимание, что<static_holder>является конкретным типом, а<static_holder_class>является шаблоном класса, поэтому спецификатор можно рассматривать как удобный способ обеспечить доступ к семейству связанных конкретных компонентов (различные возможные инстанциации шаблона класса):<flyweight>Внутренне выбирает конкретный компонент, соответствующий его внутренним потребностям.Сам компонент (например, шаблон фабричного класса).
  • Связанныйкомпонентный спецификатор, который является типом, представленным в качестве шаблонного аргументаflyweight.
  • For example, the type static_holder is a holder specifier which is used by flyweight to generate actual holder classes, in this case instantiations of the class template static_holder_class. Note that static_holder is a concrete type while static_holder_class is a class template, so a specifier can be seen as a convenient way to provide access to a family of related concrete components (the different possible instantiations of the class template): flyweight internally selects the particular component appropriate for its internal needs. [ORIG_END] -->

    Custom factories

    В некотором смысле, фабрики напоминают уникальные ассоциативные контейнеры, такие как<std::set>, хотя их ожидаемый интерфейс гораздо более лаконичен:

    // example of a possible factory class template
    template<typename Entry,typename Key>
    class custom_factory_class
    {
    public:
      typedef ... handle_type;
      
      handle_type  insert(const Entry& x);
      void         erase(handle_type h);
      const Entry& entry(handle_type h);
    };
    

    Заводы параметризированы<Entry>и<Key>: Первый — это тип хранимых объектов, а второй — тип открытого ключа, на котором работает<flyweight>(например,<std::string>в<flyweight<std::string>>или<flyweight<key_value<std::string,texture> >>). Запись имеет общую ценность, с которой связаны объекты с весом, а также внутренняя бухгалтерская информация, но с точки зрения фабрики, однако, единственный факт, известный о<Entry>, заключается в том, что она неявно конвертируема в<const Key&>, и на основе их связанных<Key>, что записи должны считаться эквивалентными или нет. Функция члена фабрики<insert()>обнаруживает ранее сохраненную запись, связанная с ней<Key>эквивалентна записи проходящего объекта<Entry>(для некоторого отношения эквивалентности<Key>по отношению к фабрике), или сохраняет новую запись, если не найден эквивалент.<handle_type>к эквивалентной или вновь вставленной записи возвращается; это<handle_type>является токеном для дальнейшего доступа к записи через<erase()>и<entry()>. Обратитесь к ссылкедля официального определения концепции<Factory>.

    Рассмотрим реальный пример реализации фабричного класса. Предположим, мы хотим отследить различные призывы Бооста. Функции «Flyweight of the<insert()>» и «<erase()>»: это можно сделать с помощью пользовательской фабрики, чьи методы «Flyweight» испускают микросообщения на консоль программы. Мы основываем реализацию функциональности репозитория на регулярной<std::set>:

    <
    template<typenameEntry,typenameKey>
    classverbose_factory_class
    {
     typedefstd::set<Entry,std::less<Key>>store_type;
     store_typestore;
    public:
     typedeftypenamestore_type::iteratorhandle_type;
     handle_typeinsert(constEntry&x)
     {
       std::pair<handle_type,bool>p=store.insert(x);
       if(p.second){/* new entry */
         std::cout<<"new: "<<(constKey&)x<<std::endl;
       }
       else{       /* existing entry */
         std::cout<<"hit: "<<(constKey&)x<<std::endl;
       }
       returnp.first;
     }
     voiderase(handle_typeh)
     {
       std::cout<<"del: "<<(constKey&)*h<<std::endl;
       store.erase(h);
     }
     constEntry&entry(handle_typeh)
     {
       return*h;
     }
    };
    
    >

    Код заслуживает некоторых комментариев:

    • < [17] >и< [18] >,< [18] >,< [18] >, [скрыто], [скрыто]. Легкость< [20] >,< [20] >,< [19] >,< [19] >,< [19] >,< [21] >,< [22] >,< [22] >, [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто].
    • Тот< [29] >,< [29] >,< [29] >,< [30] >, [< [29] >], [< [29] >], [< [32] >], [< [32] >], [< [29] >], [< [29] >], []], [< [29] >], [[]], [[]], [[]], [[]], [[]], [[]], [[]], [[]], [[]], [[]], [[]], [[]], [[]].
    • < [41] >< [41] >< [41] >< [41] >< [42] >< [42] >< [42] >< [41] >< [41] >< [41] >]< [41] >< [41] >< [41] >< [41] >]< [42] >
    .Заметим, что фабрика параметризована поEntryиKey, так как эти типы обеспечиваются внутри Boost. Легкий вес, когда фабрика создается как часть механизмаflyeight; но ничто не мешает нам иметь больше шаблонных параметров для более точной конфигурации типа фабрики: например, мы могли бы расширитьverbose_factory_class, чтобы принять некоторый сравнительный предикат, а не по умолчаниюstd::less<Key>, или указать распределитель, используемый внутреннимstd::set.
  • Тот факт, чтоEntryконвертируется вconst Key&(что является единственным свойством, известным оEntry), используется в спецификацииstd::less<Key>в качестве сравнительного предиката дляstd::setEntrys, используемого в качестве внутреннего хранилища.
  • Как наша публикаhandle_typeмы просто используем итератор для внутреннейstd::set.
  • [ORIG_END] -->

    Для того, чтобы подключить заказную фабрику к спецификации<flyweight>типа, нам нужна связанная конструкция, называемаязаводским спецификатором. Заводской спецификатор — это<Lambda Expression>, принимающий два типа аргументов<Entry>и<Key>и возвращающий соответствующий заводской класс:

    // Factory specifier (metafunction class version)
    struct custom_factory_specifier
    {
      template<typename Entry,Key>
      struct apply
      {
        typedef custom_factory_class<Entry,Key> type;
      } 
    };
    // Factory specifier (placeholder version)
    typedef custom_factory_class<
      boost::mpl::_1,
      boost::mpl::_2
    > custom_factory_specifier;
    

    Есть одна последняя деталь: чтобы реализовать<flyweight>интерфейс параметров шаблона свободного порядка, необходимо явно пометить заводской спецификатор как таковой, чтобы его можно было отличить от других типов спецификаторов. Повышаю. Flyweight предоставляет три различных механизма для выполнения этой маркировки:

    1. Устанавливается уточнение фиктивного состояния< [59] >. Сверхъестественное положение: . . . . . . . . . . . . . . . . . . . . . . . . . ..
      < [60] >
    2. Специализированный пробоотборник Специальный выпуск< [65] >:
      < [66] >
    3. Третий механизм,
      < [74] >
      < [73] >:
      < [74] >
    .Устанавливают ли уточнения из фиктивного типаfactory_marker. Обратите внимание, что этот механизм не может использоваться с выражениями заполнителей.
    #include<boost/flyweight/factory_tag.hpp>
    structcustom_factory_specifier:factory_marker
    {
     template<typenameEntry,Key>
     structapply
     {
       typedefcustom_factory_class<Entry,Key>type;
     }
    };
    
  • Специализируйте специальный шаблон класса под названиемis_factory:
    #include<boost/flyweight/factory_tag.hpp>
    structcustom_factory_specifier{};
    namespaceboost{
    namespaceflyweights{
    template<>structis_factory<custom_factory_specifier>:boost::mpl::true_{};
    }
    }
    
  • Третий механизм, наименее навязчивый, состоит в обертывании спецификатора внутри конструкцииfactory:
    #include<boost/flyweight/factory_tag.hpp>
    typedefflyweight<
     std::string,
     factory<custom_factory_specifier>
    >flyweight_string;
    
    .
  • [ORIG_END] -->

    Пример 8в разделе примеров полностью развивает описанный выше случай<verbose_factory_class>.

    Custom holders

    Держатель — класс со статической функцией<get()>, дающий доступ к уникальному экземпляру данного типа<C>:

    // example of a possible holder class template
    template<typename C>
    class custom_holder_class
    {
    public:
      static C& get();
    };
    

    <flyweight>Внутренне использует держателя для создания соответствующей фабрики, а также некоторых других глобальных данных. Спецификатор держателя - это<Lambda Expression>, принимающий тип<C>, на котором работает соответствующий класс держателя:

    // Holder specifier (metafunction class version)
    struct custom_holder_specifier
    {
      template<typename C>
      struct apply
      {
        typedef custom_holder_class<C> type;
      } 
    };
    // Holder specifier (placeholder version)
    typedef custom_holder_class<boost::mpl::_1> custom_factory_specifier;
    

    Как и в случае сзаводскими спецификаторами, спецификаторы держателей должны быть помечены, чтобы быть должным образом распознанными при предоставлении<flyweight>, и для этого существуют три доступных механизма:

    // Alternatives for tagging a holder specifier
    #include <boost/flyweight/holder_tag.hpp>
    // 1: Have the specifier derive from holder_marker
    struct custom_holder_specifier: holder_marker
    {
      ...
    };
    // 2: Specialize the is_holder class template
    namespace boost{
    namespace flyweights{
    template<> struct is_holder<custom_holder_specifier>: boost::mpl::true_{};
    }}
    // 3: use the holder<> wrapper when passing the specifier
    // to flyweight
    typedef flyweight<
      std::string,
      holder<custom_holder_specifier>
    > flyweight_string;
    

    Custom locking policies

    Пользовательская политика блокировки представляет следующий простой интерфейс:

    // example of a custom policy
    class custom_locking
    {
      typedef ... mutex_type;
      typedef ... lock_type;
    };
    

    где<lock_type>используется для приобретения/выпуска мутексов в соответствии сприложенной блокировкойидиомой:

    mutex_type m;
    ...
    {
      lock_type lk(m); // acquire the mutex
      // zone of mutual exclusion, no other thread can acquire the mutex
      ...
    } // m released at lk destruction
    

    Формальные определения понятий<Mutex>и<Scoped Lock>приведены в ссылке. Чтобы принять политику блокировки в качестве шаблонного аргумента<flyweight>, класс должен быть соответствующим образом помечен:

    // Alternatives for tagging a locking policy
    #include <boost/flyweight/locking_tag.hpp>
    // 1: Have the policy derive from locking_marker
    struct custom_locking: locking_marker
    {
      ...
    };
    // 2: Specialize the is_locking class template
    namespace boost{
    namespace flyweights{
    template<> struct is_locking<custom_locking>: boost::mpl::true_{};
    }}
    // 3: use the locking<> wrapper when passing the policy
    // to flyweight
    typedef flyweight<
      std::string,
      locking<custom_locking>
    > flyweight_string;
    

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

    Custom tracking policies

    Политики отслеживания вносят некоторую информацию о типе в процесс определения внутренней фабрики и предоставляют доступ к этой фабрике, чтобы обеспечить реализацию кода отслеживания. Политика отслеживания<Tracking>определяется как класс со следующими вложенными элементами:

    • Тип< [97] >.
    • Тип< [99] >.
    Каждый из этих элементов опирается на предыдущий в том смысле, что он увеличивается. Внутреннее оборудование с массой тела направляет результаты, полученные элементом, в следующее:
    • < [101] >< [102] >,< [103] >,< [104] >,< [103] >< [106] >,< [103] >< [103] >< [103] >< [106] >.< [107] >,< [106] >,< [101] >,,,,, [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [скрыто], [ Посвящается с помощью логической службы, с помощью логопедической системы, с помощью логопедической системы.< [103] >,< [101] >,< [101] >,< [103] >,< [101] >.
    • Бинарный< [127] >< [128] >< [129] >и< [130] >< [131] >, [чтобы], [чтобы],< [130] >[чтобы],< [128] >,< [128] >, [чтобы], [чтобы], [чтобы], [чтобы], [чтобы], [чтобы], [чтобы], [чтобы], [чтобы], [чтобы], [чтобы], [чтобы], [чтобы], [чтобы], [чтобы], [чтобы], [что], [чтобы], [что], [что], [что], [что], [что], [что], [что], [что], [что], [что], [что], [что], [что], [что], [что], [что], [что], [что], [что], [что], [что], [что], [что], [что], [
    Итак, чтобы определить фабрику некоторой инстанциации<fw_t><flyweight>,<Tracking::entry_type>вызывается с внутренним типом<Value>, неявно конвертируемым в<const fw_t::key_type&>, чтобы получить тип ввода для фабрики, который должен быть конвертируемым как в<const Value&>, так и в<const fw_t::key_type&>. Затем<Tracking::handle_type>подается внутренний тип ручки и помощник политики отслеживания для производства типа ручки завода. Наблюдательный читатель, возможно, обнаружил кажущуюся замкнутость:<Tracking::handle_type>производит тип ручки фабрики, и в то же время передается помощник отслеживания, который предоставляет доступ к фабрике. Решение этой загадки происходит от осознания того факта, что<TrackingHandler>являетсянеполным типомк моменту его передачи<Tracking::handle_type>: Только когда<Handle>будет инстанцирован на более позднем этапе, этот тип будет завершен.ТипTracking::entry_type.
  • ТипTracking::handle_type.
  • Each of these elements build on the preceding one, in the sense that Boost.Flyweight internal machinery funnels the results produced by an element into the following:
    • Tracking::entry_typeявляется.Lambda Expression, принимая два различных типа, названныхValueиKeyтак, чтоValueнеявно конвертируется вconst Key&. Предполагается, что выражение возвращает тип, неявно конвертируемый как вconst Value&, так и вconst Key&.Tracking::entry_typeсоответствует фактическому типу записей, хранящихся на фабрике,: позволяя политике отслеживания принимать участие в определении этого типа, политика может добавлять внутреннюю информацию отслеживания к данным ввода в случае необходимости. Если дополнительная информация не требуется, политика отслеживания может просто вернутьсяValueв видеTracking::entry_type.
    • БинарныйLambda ExpressionTracking::handle_typeвызывается с типамиInternalHandleиTrackingHandlerдля получения типаHandle, который будет использоваться в качестве типа ручки на фабрике.TrackingHandlerпередается в качестве аргумента шаблонаTracking::handle_type, чтобы предложить функциональность, поддерживающую реализацию кода отслеживания.
    So, in order to define the factory of some instantiation fw_t of flyweight, Tracking::entry_type is invoked with an internal type Value implicitly convertible to const fw_t::key_type& to obtain the entry type for the factory, which must be convertible to both const Value& and const fw_t::key_type&. Then, Tracking::handle_type is fed an internal handle type and a tracking policy helper to produce the factory handle type. The observant reader might have detected an apparent circularity: Tracking::handle_type produces the handle type of the flyweight factory, and at the same time is passed a tracking helper that grants access to the factory being defined! The solution to this riddle comes from the realization of the fact that TrackingHandler is an incomplete type by the time it is passed to Tracking::handle_type: only when Handle is instantiated at a later stage will this type be complete. [ORIG_END] -->

    Для того, чтобы политика отслеживания была передана<flyweight>, она должна быть помечена так же, как и остальные спецификаторы.

    // Alternatives for tagging a tracking policy
    #include <boost/flyweight/tracking_tag.hpp>
    // 1: Have the policy derive from tracking_marker
    struct custom_tracking: tracking_marker
    {
      ...
    };
    // 2: Specialize the is_tracking class template
    namespace boost{
    namespace flyweights{
    template<> struct is_tracking<custom_tracking>: boost::mpl::true_{};
    }}
    // 3: use the tracking<> wrapper when passing the policy
    // to flyweight
    typedef flyweight<
      std::string,
      tracking<custom_tracking>
    > flyweight_string;
    

    Политики отслеживания являются их собственными спецификаторами, то есть они предоставляются непосредственно в качестве аргументов шаблона для шаблона класса<flyweight>.




    Пересмотрено 1 сентября 2014 года

    © Copyright 2006-2014 Joaquín M López Muñoz. Распространяется под лицензией Boost Software License, версия 1.0. (См. сопроводительный файлLICENSE_1_0.txtили копию на) http://www.boost.org/LICENSE_1_0.txt

    Статья Boost.Flyweight Documentation - Tutorial - Extending Boost.Flyweight раздела Boost.Flyweight Documentation - Tutorial может быть полезна для разработчиков на c++ и boost.




    Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



    :: Главная :: Boost.Flyweight Documentation - Tutorial ::


    реклама


    ©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
    Top.Mail.Ru

    Время компиляции файла: 2024-08-30 11:47:00
    2025-07-05 03:33:13/0.007551908493042/0