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

Chapter 1. Boost.Functional/Factory 1.0

Boost , Chapter 1. Boost.Functional/Factory 1.0 ,

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

Chapter 1. Boost.Functional/Factory 1.0

Tobias Schwinger

Distributed under the Boost Software License, Version 1.0. (См. сопроводительный файл LICENSE_1_0.txt или копия на http://www.boost.org/LICENSE_1_0.txt)

Шаблон boost::factory позволяет инкапсулировать new выражение как объект функции, boost:: value_factory инкапсулирует конструктора без new.

boost::factory<T*>()(arg1,arg2,arg3)
// same as new T(arg1,arg2,arg3)
boost::value_factory<T>()(arg1,arg2,arg3)
// same as T(arg1,arg2,arg3)

По техническим причинам аргументы для функциональных объектов должны быть LValues. Фабрика, которая также принимает RValues, может быть составлена с использованием boost::forward_adapter или boost::bind>.

В традиционном ориентированном на объект программировании фабрика является объектом, реализующим интерфейс одного или нескольких методов, которые строят объекты, соответствующие известным интерфейсам.

// assuming a_concrete_class and another_concrete_class are derived
// from an_abstract_class
class a_factory
{
  public:
    virtual an_abstract_class* create() const = 0;
    virtual ~a_factory() { }
};
class a_concrete_factory : public a_factory
{
  public:
    virtual an_abstract_class* create() const
    {
        return new a_concrete_class();
    }
};
class another_concrete_factory : public a_factory
{
  public:
    virtual an_abstract_class* create() const
    {
        return new another_concrete_class();
    }
};
// [...]
int main()
{
    boost::ptr_map<std::string,a_factory> factories;
    // [...]
    factories.insert("a_name",std::auto_ptr<a_factory>(
        new a_concrete_factory));
    factories.insert("another_name",std::auto_ptr<a_factory>(
        new another_concrete_factory));
    // [...]
    std::auto_ptr<an_abstract_class> x(factories.at(some_name).create());
    // [...]
}

Этот подход имеет несколько недостатков. Самым очевидным является то, что существует множество котел-кодов. Другими словами, существует слишком много кода, чтобы выразить довольно простое намерение. Мы могли бы использовать шаблоны, чтобы избавиться от некоторых из них, но подход остается негибким:

  • Нам может понадобиться фабрика, которая принимает некоторые аргументы, которые направляются конструктору,
  • мы, вероятно, хотим использовать умные указатели,
  • мы можем хотеть несколько функций-членов для создания различных видов объектов,
  • нам не обязательно нужен полиморфный базовый класс для объектов,
  • как мы увидим, нам вообще не нужен заводский базовый класс,
  • мы можем просто позвонить конструктору - без new создать объект на стеке, и
  • наконец, мы можем использовать индивидуальные управления памятью.

Опыт показал, что использование функциональных объектов и общих компонентов Boost для их состава, Design Patterns, которые описывают механизмы обратного вызова (как правило, требующий высокого процента котел-кода с чистой методологией объект-ориентированной) становятся реализуемыми с помощью всего нескольких строк кода и без дополнительных классов.

Фабрики - это механизмы обратного вызова для конструкторов, поэтому мы предоставляем два шаблона класса: boost:: value_factory и boost::factory, которые инкапсулируют конструкцию объекта путем прямого применения конструктора и new оператора, соответственно.

Мы позволяем функциям направлять свои аргументы в пользу выражений, которые они инкапсулируют. Над этим boost::фабрикатор опционально позволяет использовать умные указатели и Аллократы.

Полиморфизм комбинированного времени может использоваться там, где это необходимо,

template< class T >
void do_something()
{
    // [...]
    T x = T(a,b);
    // for conceptually similar objects x we neither need virtual
    // functions nor a common base class in this context.
    // [...]
}

Теперь, чтобы разрешить неоднородные подписи для конструкторов типов, переданных для T, мы можем использовать value_factory и boost::bind для нормализации между ними.

template< class ValueFactory >
void do_something(ValueFactory make_obj = ValueFactory())
{
    // [...]
    typename ValueFactory::result_type x = make_obj(a,b);
    // for conceptually similar objects x we neither need virtual
    // functions nor a common base class in this context.
    // [...]
}
int main()
{
    // [...]
    do_something(boost::value_factory<X>());
    do_something(boost::bind(boost::value_factory<Y>(),_1,5,_2));
    // construct X(a,b) and Y(a,5,b), respectively.
    // [...]
}

Может быть, мы хотим, чтобы наши объекты пережили объем функции, в этом случае мы должны использовать динамические распределения;

template< class Factory >
whatever do_something(Factory new_obj = Factory())
{
    typename Factory::result_type ptr = new_obj(a,b);
    // again, no common base class or virtual functions needed,
    // we could enforce a polymorphic base by writing e.g.
    //    boost::shared_ptr<base>
    // instead of
    //    typename Factory::result_type
    // above.
    // Note that we are also free to have the type erasure happen 
    // somewhere else (e.g. in the constructor of this function's
    // result type).
    // [...]
}
// [... call do_something like above but with __factory__ instead
// of __value_factory__]

Хотя мы могли создать полиморфные объекты в предыдущем примере, мы использовали полиморфизм времени компиляции для фабрики. Если мы хотим стереть тип фабрики и таким образом разрешить полиморфизм во время запуска, мы можем использовать Boost.Function для этого. Первый пример можно переписать следующим образом.

typedef boost::function< an_abstract_class*() > a_factory;
// [...]
int main()
{
    std::map<std::string,a_factory> factories;
    // [...]
    factories["a_name"] = boost::factory<a_concrete_class*>();
    factories["another_name"] =
        boost::factory<another_concrete_class*>();
    // [...]
}

Конечно, мы можем так же легко создавать фабрики, которые принимают аргументы и/или возвращают Smart Pointers.

Description

Шаблон функционального объекта, который вызывает конструктора типа T.

Header
#include <boost/functional/value_factory.hpp>
Synopsis
namespace boost
{
    template< typename T >
    class value_factory;
}

Notation

T

произвольный тип с по крайней мере одним общественным конструктором

a0...aN

аргумент LValues конструктору T

F

тип value_factory<F>

f

экземпляр объекта F

Expression Semantics

Выражение

Семантика

F()

создает объект типа F.

F(f)

создает объект типа F.

f(a0...aN)

возвратит T(a0...aN).

F::результат_type

- это тип T.

Limits

BOOST_FUNCTIONAL_VALUE_FACTORY_MAX_ARITY может быть определено, чтобы установить максимальную редкость. По умолчанию 10.

Description

Шаблон функционального объекта, который динамически конструирует объект указателя для типа указателя, заданного как аргумент шаблона. Умные указатели могут быть использованы для аргумента шаблона, учитывая, что boost::pointee<Pointer>::type дает указательный тип.

Если дается Аллоктор, он используется для распределения памяти и для построения объекта используется форма размещения new. Функциональный объект, который называет деструктором и передает память с копией Аллокатора, используется для второго аргумента конструктора Pointer (так это должен быть Smart Pointer, который предоставляет подходящий конструктор, такой как boost::shared_ptr).

Если третий аргумент шаблона factory_passes_alloc_to_smart_pointer, то сам аллокат используется для третьего аргумента конструктора Pointer (boost::shared_ptr затем использует аллокататор для управления памятью отдельно выделенного контрольного счетчика).

Header
#include <boost/functional/factory.hpp>
Synopsis
namespace boost
{
    enum factory_alloc_propagation
    {
        factory_alloc_for_pointee_and_deleter,
        factory_passes_alloc_to_smart_pointer
    };
    template< typename Pointer,
        class Allocator = void,
        factory_alloc_propagation AllocProp =
            factory_alloc_for_pointee_and_deleter >
    class factory;
}

Notation

T

произвольный тип с по крайней мере одним общественным конструктором

P

указатель или умный указатель на T

a0...aN

аргумент LValues конструктору T

F

тип фабрика<P>

f

экземпляр объекта F

Expression Semantics

Выражение

Семантика

F()

создает объект типа F.

F(f)

создает объект типа F.

f(a0...aN)

динамически создает объект типа T, используя a0...aN в качестве аргументов для конструктора.

F::результат_type

- тип P с удаленными верхними кв-квалификаторами.

Limits

BOOST_FUNCTIONAL_FACTORY_MAX_ARITY может быть определено, чтобы установить максимальную редкость. По умолчанию 10.

Boost 1.58.0

Для того, чтобы снять зависимость от Boost. Опционный параметр по умолчанию для аллоцаторов был изменен с boost::none_t на void. Если у вас есть код, который перестал работать, потому что он использует boost::none_t, быстрое исправление заключается в определении BOOST_FUNCTIONAL_FACTORY_SUPPORT_NONE_T, которое восстановит поддержку, но это будет удалено в будущем выпуске. Это должно быть относительно легко исправить должным образом.

Эрик Ниблер попросил функцию вызвать конструктора типа (с аргументами, представленными как Тупле) в качестве функции Fusion. Эти заводские утилиты - факторинговое обобщение этой идеи.

Дэйв Абрахамс предложил поддержку Smart Pointer для безопасности исключений, предоставляя полезные подсказки для реализации.

Стиль документации Джоэля де Гузмана был скопирован из Fusion.

Кроме того, я хочу поблагодарить Питера Димова за то, что он поделился своими знаниями о языковых деталях и их эволюции.

  1. Определенные шаблоны, Гамма и др. - Эддисон Уэсли Издатель, 1995 год
  2. Стандартное руководство библиотечного программиста по шаблону, компания Hewlett-Packard, 1994
  3. Боост.Бинд, Петр Димов, 2001-2005
  4. Boost.Function, Douglas Gregor, 2001-2004

Последний пересмотр: 1 ноября 2008 года в 21:44:52 GMT


Статья Chapter 1. Boost.Functional/Factory 1.0 раздела Chapter 1. Boost.Functional/Factory 1.0 может быть полезна для разработчиков на c++ и boost.




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



:: Главная :: ::


реклама


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

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 17:00:20/0.028875827789307/1