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

Extending Actors

Boost , Chapter 1. Phoenix 3.2.0 , Advanced Examples

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

PrevUpHomeNext

Актерыявляются одной из основных частей библиотеки и одним из многих пунктов настройки. Реализация по умолчанию обеспечивает несколько операторных () перегрузок, которые связаны с оценкой выражений.

Для некоторых случаев использования этого может быть недостаточно. Для удобства можно представить пользовательские функции-члены, которые генерируют новые выражения. Примером может служитьif_else_ Statement, которое предоставляет дополнительный элемент для генерации ленивого if-else выражения. При этом настоящее выражение Феникса становится более выразительным.

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

Requirements

Давайте повторим то, что мы хотим иметь:

выражение

Семантика

<a.begin()>

Возвращает итератор, указывающий на первый элемент в контейнере.

<a.end()>

Возвращает итератор, указывающий на последний элемент в контейнере.

<a.size()>

Возвращает размер контейнера, то есть его количество элементов.

<a.max_size()>

Возвращает самый большой размер, который может иметь этот контейнер.

<a.empty()>

Эквивалент размера a.size() == 0. (Но, возможно, быстрее.)

<a.swap(b)>

Эквивалент свопа (a,b)

Кроме того, мы хотим, чтобы все оператор () перегрузки обычного актера.

Defining the actor

Первая версия нашего<container_actor>интерфейса покажет общий принцип. Это будет постоянно расширяться. Для простоты каждый генератор функций элемента сначала возвращает<nothing>.

template <typename Expr>
struct container_actor
	: actor<Expr>
{
	typedef actor<Expr> base_type;
	typedef container_actor<Expr> that_type;
	
	container_actor( base_type const& base )
		: base_type( base ) {}
	expression::null<mpl::void_>::type const begin() const { return nothing; }
	expression::null<mpl::void_>::type const end() const { return nothing; }
	expression::null<mpl::void_>::type const size() const { return nothing; }
	expression::null<mpl::void_>::type const max_size() const { return nothing; }
	expression::null<mpl::void_>::type const empty() const { return nothing; }
	// Note that swap is the only function needing another container.
	template <typename Container>
	expression::null<mpl::void_>::type const swap( actor<Container> const& ) const { return nothing; }
};
Using the actor

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

Во-первых, давайте создадим генератор, который обернет<container_actor>вокруг любого другого выражения:

template <typename Expr>
container_actor<Expr> const
container( actor<Expr> const& expr )
{
    return expr;
}

Теперь давайте проверим это:

std::vector<int> v;
v.push_back(0);
v.push_back(1);
v.push_back(2);
v.push_back(3);
(container(arg1).size())(v);

Конечно, это не очень элегантно и не очень практично (мы могли бы просто использовать Феникс::begin(v) измодуля алгоритма Феникса, но мы можем сделать лучше).

Давайте возьмемзаполнитель аргумента, который можно использовать, как если бы это был контейнер STL:

container_actor<expression::argument<1>::type> const con1;
// and so on ...

Приведенный выше пример можно переписать как:

std::vector<int> v;
v.push_back(0);
v.push_back(1);
v.push_back(2);
v.push_back(3);
(con1.size())(v);

Вау, это было легко!

Adding life to the actor

Это будет еще проще!

Во-первых, мы определяем ленивую функцию, которая оценивает выражение, которое мы хотим реализовать. Ниже приводится реализация функции размера:

struct size_impl
{
	// result_of protocol:
	template <typename Sig>
	struct result;
	template <typename This, typename Container>
	struct result<This(Container)>
	{
		// Note, remove reference here, because Container can be anything
		typedef typename boost::remove_reference<Container>::type container_type;
		// The result will be size_type
		typedef typename container_type::size_type type;
	};
	template <typename Container>
	typename result<size_impl(Container const&)>::type
	operator()(Container const& container) const
	{
		return container.size();
	}
};

Хорошо, это была первая часть. Во второй части будет реализована функция размера члена<container_actor>:

template <typename Expr>
struct container_actor
	: actor<Expr>
{
	typedef actor<Expr> base_type;
	typedef container_actor<Expr> that_type;
	
	container_actor( base_type const& base )
		: base_type( base ) {}
	typename expression::function<size_impl, that_type>::type const
	size() const
	{
		function<size_impl> const f = size_impl();
		return f(*this);
	}
	// the rest ...
};

В качестве упражнения пользователю остается выполнить недостающие части, повторно используя функции измодуля алгоритма Феникса(нетерпеливый взгляд здесь:container_actor.cpp).


PrevUpHomeNext

Статья Extending Actors раздела Chapter 1. Phoenix 3.2.0 Advanced Examples может быть полезна для разработчиков на c++ и boost.




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



:: Главная :: Advanced Examples ::


реклама


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

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