вопрос по метапрограммированию
От: CyberZX  
Дата: 18.10.05 00:02
Оценка:
допустим есть у нас набор шаблонных классов, которые наследуют от своего параметра


из них я хочу сгенерировать класс, имеющий сложную иерархическую структуру


вроде все хорошо. но проблема вот в чем. у меня в дереве MyStruct имеется два различных класса A, которые все же имеют функцию foo с одинаковой сигнатурой. поэтому я не могу просто вызвать my_struct.foo() из-за возникающей неоднозначности.

меня интересует, есть ли какие-нибудь известные методы для того, что бы как-нибудь помечать конкретные классы в иерархии и потом получать к ним доступ? естесственно интересует только compile-time, в run-time все далется тривиально через dynamic_cast
а мне бы хотелось как-нибудь вот так tag_cast<first_A_class_tag>(my_struct).foo(); tag_cast<second_A_class_tag>(my_struct).foo();
что-то пока никакое решение в голову не приходит
Re: вопрос по метапрограммированию
От: crable США  
Дата: 18.10.05 05:01
Оценка:
Здравствуйте, CyberZX, Вы писали:

CZX>допустим есть у нас набор шаблонных классов, которые наследуют от своего параметра

CZX>

CZX>из них я хочу сгенерировать класс, имеющий сложную иерархическую структуру

CZX>

CZX>вроде все хорошо. но проблема вот в чем. у меня в дереве MyStruct имеется два различных класса A, которые все же имеют функцию foo с одинаковой сигнатурой. поэтому я не могу просто вызвать my_struct.foo() из-за возникающей неоднозначности.


CZX>меня интересует, есть ли какие-нибудь известные методы для того, что бы как-нибудь помечать конкретные классы в иерархии и потом получать к ним доступ? естесственно интересует только compile-time, в run-time все далется тривиально через dynamic_cast

CZX>а мне бы хотелось как-нибудь вот так tag_cast<first_A_class_tag>(my_struct).foo(); tag_cast<second_A_class_tag>(my_struct).foo();
CZX>что-то пока никакое решение в голову не приходит
Может так?
struct E {};

template <typename T>
struct A: public T
{
        void foo() { cout << "A<T>::foo()\n"; }
};
// специализация просто, чтобы показать вызов foo из A<E>
template <>
void A<E>::foo() { cout << "A<E>::foo()\n"; }

template <typename T>
struct B: public T {};

template <typename T, typename U>
struct C: public T, public U {};

struct M: public A<C<B<E>, A<E> > >
{
        void foo1() { A<C<B<E>, A<E> > >::foo(); }
        void foo2() { A<E>::foo(); }
};
  
int main()
{
        M        m;
        m.foo1();
        m.foo2();
  
        return 0;
}
The last good thing written in C was Franz Schubert's Symphony No. 9.
Re: вопрос по метапрограммированию
От: Death_Mokar Украина  
Дата: 18.10.05 06:28
Оценка:
Здравствуйте, CyberZX, Вы писали:



CZX>вроде все хорошо. но проблема вот в чем. у меня в дереве MyStruct имеется два различных класса A, которые все же имеют функцию foo с одинаковой сигнатурой. поэтому я не могу просто вызвать my_struct.foo() из-за возникающей неоднозначности.


CZX>меня интересует, есть ли какие-нибудь известные методы для того, что бы как-нибудь помечать конкретные классы в иерархии и потом получать к ним доступ? естесственно интересует только compile-time, в run-time все далется тривиально через dynamic_cast

CZX>а мне бы хотелось как-нибудь вот так tag_cast<first_A_class_tag>(my_struct).foo(); tag_cast<second_A_class_tag>(my_struct).foo();
CZX>что-то пока никакое решение в голову не приходит

Неоднозначность можно разрешить явно указав "путь" к функции:

my_struct.A::B::Binary::D::A::foo();


Или использовать виртуальное наследование чтобы в my_struct была одна копия класса А.

Вроде так.
улыбок тебе дед мокар
Re: вопрос по метапрограммированию
От: Anton V. Kolotaev  
Дата: 18.10.05 12:13
Оценка:
Здравствуйте, CyberZX, Вы писали:


А может быть лучше вместо параметризации классов предком параметризовать их наследником (CRTP как в ATL)?


 
#define DECLARE_DERIVED_AS_SELF \
    Derived const & self() const { return static_cast<Derived const &>(*this); }  \
    Derived       & self() const { return static_cast<Derived       &>(*this); }

template <class Derived> struct A
{
    void do_something();
    A &  a() { return *this; }
private:
    DECLARE_DERIVED_AS_SELF
};

template <class Derived> struct B
{
    void do_something();
    B &  b() { return *this; }
private:
    DECLARE_DERIVED_AS_SELF
};

template <class Derived> struct C
{
    void somefunc()
    {
        self().a().do_something();
        self().b().do_something();
    }
    C &  c() { return *this; }
private:
    DECLARE_DERIVED_AS_SELF
};


Список базовых классов задавать mpl::vector'ом унарных метафункций (точнее: лямбда выражений):


namespace mpl = boost::mpl;

typedef mpl::placeholders::_  __;

struct bases : mpl::vector<A<__>, B<__>, C<__> > {};


И генерировать сам класс таким образом:


template <class Base, class Node, class Derived>
    struct inherit_and_apply_on_derived : Base, mpl::apply<Node, Derived>::type
{
};

struct D : mpl::inherit_linearly<bases, inherit_and_apply_on_derived<__, __, D> >::type
{};


Вполне жизнеспособный дизайн...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.