Требуется создать новый примешанный класс Mix (серию классов), расширяющий функционал некоторого метода foo() уже существующего класса A. Метод foo() класса наследника A и Mix, выполняет и операторы A::foo() и операторы Mix::foo().
Попытка соорудить такой класс:
struct A
{
void foo()
{
cout << "A action";
}
};
template<class D>
struct Mix
{
void foo()
{
D* self = static_cast<D*>(this);
self->foo();
cout << "Mix action";
}
};
struct AM: public A, public Mix<AM> {} ;
int main() {
AM am;
am.foo();
return 0;
}
// error: request for member 'foo' is ambiguous
Я вот как-то так делаю. Идея в том, что каждый микс наследует базу и все предыдущие.
using boost::mpl::fold;
using boost::mpl::vector;
using boost::mpl::quote1;
using boost::mpl::quote2;
using boost::mpl::bind2;
using boost::mpl::apply_wrap1;
using boost::mpl::placeholders::_1;
using boost::mpl::placeholders::_2;
using boost::mpl::is_sequence;
template
<
typename Comp,
typename T,
typename Owner,
unsigned int PropId_ = 0
>
class component_base;
template
<
typename T,
typename Owner,
typename Mixes,
unsigned int PropId_ = 0
>
class component_t : public
fold
<
Mixes,
component_base
<
component_t<T, Owner, Mixes, PropId_>,
T, Owner, PropId_
>,
apply_wrap1<_2, _1>
>::type
{
private:
static_assert(is_sequence<Mixes>::value, "Must be an MPL sequence.");
friend comp_accessor;
using inherited = typename
fold
<
Mixes,
component_base
<
component_t<T, Owner, Mixes, PropId_>,
T, Owner, PropId_
>,
apply_wrap1<_2, _1>
>::type;
public:
using inherited::inherited;
};
template <char const *Str_>
struct str_wrp
{
static char const *value() { return Str_; }
};
template <typename T, typename Owner, char const *NetnodeName_, unsigned int PropId_ = 0>
using noevent_pst_comp_t = component_t
<
T, Owner,
vector<bind2<quote2<persist_mix>, _1, str_wrp<NetnodeName_>>>
>;
Здравствуйте, gencoder, Вы писали:
Может проще
struct A
{
void foo()
{
::std::cout << "A action";
}
};
template< typename tn_Base >
struct Mix
: public tn_Base
{
void foo()
{
tn_Base::foo();
::std::cout << "Mix action";
}
};
using
AM = Mix< A >;
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Здравствуйте, VTT, Вы писали:
> Может проще
собственно работает и в случае серии примесей:
struct A
{
void foo() { cout << "A action\n"; }
};
template< typename tn_Base >
struct Mix1: public tn_Base
{
void foo() {
tn_Base::foo();
std::cout << "Mix1 action\n";
}
};
template< typename tn_Base >
struct Mix2: public tn_Base
{
void foo() {
tn_Base::foo();
std::cout << "Mix2 action\n";
}
};
using AM = Mix2< Mix1< A > >;
int main() {
AM am;
am.foo();
return 0;
}
Здравствуйте, gencoder, Вы писали:
G>Требуется создать новый примешанный класс Mix (серию классов), расширяющий функционал некоторого метода foo() уже существующего класса A. Метод foo() класса наследника A и Mix, выполняет и операторы A::foo() и операторы Mix::foo().
Чем так плохо?
#include <iostream>
using namespace std;
struct Base { virtual ~Base() {} };
struct A : Base {
virtual void foo() { cout << "A action\n"; }
};
template<class D> struct Mix : D { typedef D parent;
void foo() {
parent::foo();
cout << "Mix action\n";
}
};
struct AM : Mix<A> {} ;
int main() {
AM am;
am.foo();
return 0;
}