value адвайсы

Vladimir Migashko edited this page Dec 26, 2013 · 10 revisions

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

Value-адвайс аналогичен обычному адвайсу, за исключением того, что внедряется в аспект через агрегацию. Описывается он с помощью конструкции fas::value:

typedef fas::value<_counter_, int> counter_advice;

Этот тип адвайсов удобен для вынесения в аспект класса отдельных полей аспектного класса. Если необходимо описать часть состояния одним адвайсом, то делается это промежуточную структуру, которая вноситься в аспект как обычный адвайс.

Доступ к обычному адвайсу и value-адвайсу семантически идентичен. Любой C++ класс, объект которого можно создать с конструктором по умолчанию, и который может быть использован в качестве базового, может быть вынесен в аспект как обычный адвайс, так и как value-адвайс. Однако, в последнем случае, если адвайс не имеет состояния, он все равно увеличивает sizeof аспектного класс 1 байт, т.к. внедряется через агрегацию. Это может иметь значение если аспектный класс не имеет состояния, но реализует обширный функционал, который вынесен в аспекты.

В следующем примере sizeof(counter<>) равен sizeof(int), что соответствует внедренному fas::value<_counter_, int>. Если оставшиеся три авдвайса внедрить как value-адвайсы (т.е. просто заменить fas::advice на fas::value), то соответственно увеличиться и sizeof(counter<>). В большинстве систем размер увеличиться с четырех байт до восьми (по одному байту на каждый дополнительный value-адвайс и плюс один байт на выравнивание)

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

struct _counter_;
struct _inc_;
struct _dec_;
struct _show_;

struct ad_inc
{
  template<typename T>
  void operator()(T& t)
  {
    t.get_aspect().template get<_counter_>()++;    
  }
};

struct ad_dec
{
  template<typename T>
  void operator()(T& t)
  {
    t.get_aspect().template get<_counter_>()--;    
  }
};

struct ad_show
{
  template<typename T>
  void operator()(T& t) const
  {
    typedef typename T::aspect::template advice_cast<_counter_>::type value_type;
    value_type counter = t.get_aspect().template get<_counter_>();
    std::cout << "counter: " << counter << std::endl;
  }
};

struct counter_aspect: fas::aspect< fas::type_list_n<
  fas::value<_counter_, int>,
  fas::advice<_inc_, ad_inc>,
  fas::advice<_dec_, ad_dec>,
  fas::advice<_show_, ad_show>
>::type > {};

template<typename A = fas::aspect<> >
class counter
  : public fas::aspect_class< typename fas::merge_aspect<A, counter_aspect>::type >
{
public:
  void inc() { this->get_aspect().template get<_inc_>()(*this); }
  void dec() { this->get_aspect().template get<_dec_>()(*this); }
  int get() const { return this->get_aspect().template get<_counter_>(); }
  void show() const { this->get_aspect().template get<_show_>()(*this); }
};

int main()
{
  counter<> c;
  c.inc(); c.inc(); c.inc();  
  c.dec();
  c.show();
}