Алиасы

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

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

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

typedef fas::alias<_foo_, _bar_> foo_advice;

Первым параметром задается новый тег, по которому можно обращаться к адвайсу помеченному тегом, который передается вторым параметром. Можно задавать алиас на алиас любого уровня вложенности, но в случае зацикливания, компилятор выдаст ошибку error: incomplete type ‘fas::recursive_alias....

Алиасы могут быть использованы для согласования адвайсов различных аспектов. Например, в примере ниже, используется адвайс для отображения значения счетчика, позаимствованный из некоторого "другого" проекта:

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

namespace other {
  
struct _value_;

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

}  // namespace other

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 counter_aspect: fas::aspect< fas::type_list_n<
  fas::value_advice<_counter_, int>,
  fas::advice<_inc_, ad_inc>,
  fas::advice<_dec_, ad_dec>,
  fas::advice<_show_, other::ad_show>,
  fas::alias<other::_value_, _counter_>
>::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();
}

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