В настоящее время я играю с миксиновыми слоями, и я застрял с
досадная проблема.
Давайте рассмотрим следующий основной слой миксинов:
template <typename Next>
struct Layer1 : public Next
{
struct A : public Next::A
{
void f() { g(); }
void g() {}
};
};
Ничего особенного, просто простой миксин с двумя методами f()
и g()
.
Обратите внимание, что вызов g()
из f()
статически привязан к этому
специфический Layer1::A::g()
.
Теперь, что я хочу, чтобы иметь возможность полностью подключить методы этого
mixin для реализации, скажем, слоя логирования:
template <typename Next>
struct Layer2 : public Next
{
struct A : public Next::A
{
void f()
{
std::cout << "Layer2::A::f() [enter]" << std::endl;
Next::A::f();
std::cout << "Layer2::A::f() [leave]" << std::endl;
}
void g()
{
std::cout << "Layer2::A::g() [enter]" << std::endl;
Next::A::g();
std::cout << "Layer2::A::g() [leave]" << std::endl;
}
};
};
Учитывая Layer2<Layer1<...>>
, проблема здесь в том, что любой вызов
f()
и g()
от уровня выше Layer2
будут правильно каскадно опуститься до
Layer2::A::g()
, и, таким образом, отображать правильные сообщения регистрации. Но
любой вызов f()
и g()
снизу Layer2
не будет ничего регистрировать, поскольку
вызов был бы статически привязан к g()
, доступному на
время звонка было сделано.
Это означает, что вызов f()
с любого уровня выше Layer2
, очевидно,
по-прежнему всегда звоните Layer1::A::g()
с Layer1::A::f()
и не отображайте
протоколирование сообщений.
Я придумал 2 решения этой проблемы:
Виртуальность: явно не приемлемо. Весь смысл смешанных слоев
это избегать виртуальности, когда это не нужно.
Добавление параметра шаблона в слои для предоставления предыдущего
слой, что-то в этом роде.
.
template <typename Next, template <typename> class Prev>
struct Layer2 : public Next
{
typedef Next next_t;
struct A : public Next::A
{
void f()
{
std::cout << "Layer2::A::f() [enter]" << std::endl;
Next::A::f();
std::cout << "Layer2::A::f() [leave]" << std::endl;
}
void g()
{
std::cout << "Layer2::A::g() [enter]" << std::endl;
Next::A::g();
std::cout << "Layer2::A::g() [leave]" << std::endl;
}
};
};
template <typename Next, template <typename> class Prev>
struct Layer1 : public Next
{
typedef Next next_t;
struct A : public Next::A
{
void f()
{
std::cout << "Layer1::A::f() [enter]" << std::endl;
((typename Prev<Layer1<Next,Prev> >::A*)this)->g();
std::cout << "Layer1::A::f() [leave]" << std::endl;
}
void g()
{
std::cout << "Layer1::A::g() [enter]" << std::endl;
std::cout << "Layer1::A::g() [leave]" << std::endl;
}
};
};
typedef Layer2<Layer1<Layer0,Layer2>,NullType> Application;
Ну, это работает, но я хотел бы скрыть этот второй шаблон
параметр, так как он является избыточным.
Интересно, сталкивался ли кто-нибудь из вас с такой проблемой, и что
Решения, которые вы разработали, чтобы решить это, так как существует явный недостаток
статей на миксиновых слоях.