примешанный класс для расширения функциональности метода
От: gencoder  
Дата: 28.12.16 15:25
Оценка:
Требуется создать новый примешанный класс 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
множественное наследование
Re: примешанный класс для расширения функциональности метода
От: swingus  
Дата: 28.12.16 16:03
Оценка:
Я вот как-то так делаю. Идея в том, что каждый микс наследует базу и все предыдущие.


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, Вы писали:
Re[2]: примешанный класс для расширения функциональности метода
От: antropolog  
Дата: 28.12.16 16:24
Оценка:
Здравствуйте, swingus, Вы писали:

скажи пожалуйста, а где ты работаешь? Крайне не хотелось бы осчастливиться поддержкой подобного кода.
Re[2]: примешанный класс для расширения функциональности метода
От: push  
Дата: 28.12.16 19:36
Оценка:
Ахахаха Яркий прикол!
Re: примешанный класс для расширения функциональности метода
От: VTT http://vtt.to
Дата: 29.12.16 06:58
Оценка: 1 (1)
Может проще
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 >;
Говорить дальше не было нужды. Как и все космонавты, капитан Нортон не испытывал особого доверия к явлениям, внешне слишком заманчивым.
Re[2]: примешанный класс для расширения функциональности метода
От: gencoder  
Дата: 29.12.16 07:35
Оценка:
Здравствуйте, 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;
}
Re: примешанный класс для расширения функциональности метода
От: kov_serg Россия  
Дата: 29.12.16 13:54
Оценка:
Здравствуйте, 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;
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.