Ремуверы

migashko edited this page Nov 26, 2012 · 3 revisions

Главная, Основные концепции, АОП, Адвайсы

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

  • При объединении аспектов, адвайс первого аспекта, внедренный с некоторым тегом, замещает адвайсы последующих аспектов, с этими же тегами. Т.е. по конкретному тегу доступен последний внедренный адвайс. Однако, последующие адвайсы, также участвуют в формировании аспектного класса, хотя и не доступны. Если такие адвайсы имеют состояние, или в конструкторе производят какие либо вычисления, имеет смысл их физически удалить их из аспекта, чтобы они не увеличивали sizeof аспектного класса и/или, чтобы не влияли на время создания объекта такого класса.
  • Вы разрабатываете аспектый класс на базе существующего аспекта, однако приходите к выводу, что часть функционала этого аспекта вам не требуется. С помощью ремуверов вы можете удалить необходимый функционал.

С помощью ремуверов можно удалить любой тип адвайсов, включая алиасы и группы. Аналогично форвардам, ремувер удаляет только те адвайсы, которые внедрены в аспект после него.

#include <fas/aop.hpp>
#include <iostream>

struct _array_;

template<int S>
struct ad_array
{
  int arr[S];
};

struct aspect1: fas::aspect< fas::advice<_array_, ad_array<10> > >{};

struct aspect2: fas::aspect< fas::type_list_n<
  fas::advice<_array_, ad_array<3> >,
  aspect1
>::type >{};

struct aspect3: fas::aspect< fas::type_list_n<
  fas::advice<_array_, ad_array<3> >,
  fas::remover<_array_>,
  aspect1
>::type >{};

struct aspect4: fas::aspect<  fas::type_list_n<
  fas::advice< _array_, ad_array<1> >,
  fas::remover<_array_>,
  aspect2
>::type >{};

int main()
{
  std::cout << "sizeof(fas::aspect_class<aspect1>) = " << sizeof(fas::aspect_class<aspect1>) << std::endl;
  std::cout << "sizeof(fas::aspect_class<aspect2>) = " << sizeof(fas::aspect_class<aspect2>) << std::endl;
  std::cout << "sizeof(fas::aspect_class<aspect3>) = " << sizeof(fas::aspect_class<aspect3>) << std::endl;
  std::cout << "sizeof(fas::aspect_class<aspect4>) = " << sizeof(fas::aspect_class<aspect4>) << std::endl;
}

В этом примере показаны четыре аспекта:

  • aspect1 состоит из одного адвайса с массивом int[10]. Соответственно sizeof аспекта класса будет равен 40 байтам (в зависимости от платформы, этот размер может быть другим)
  • aspect2 объединяет адвайс с массивом int[3] и aspect1 - sizeof будет равен 52 байтам
  • aspect3 аналогичен аспекту aspect2, но перед внедрением aspect1, указан ремувер, который удалит последующие адвайсы с тегом _array_. Поэтому sizeof аспекта класса будет равен 12 байтам
  • aspect4 объединяет адвайс с массивом int[1] и аспект aspect2, который включает адвайсы int[3], int[10]. Как и предыдущих аспектах все адайсы включены с тегом _array_. Ремувер, который включен перед aspect2 удалит из аспекта оба адвайса:
sizeof(fas::aspect_class<aspect1>) = 40
sizeof(fas::aspect_class<aspect2>) = 52
sizeof(fas::aspect_class<aspect3>) = 12
sizeof(fas::aspect_class<aspect4>) = 4

Помимо одиночного тега, в ремувер можно передавать и список тегов, например так:

fas::remover< fas::type_list_n<_tag3_, _tag5_>::type >