static_cast<final_class*>(this)
От: Аноним  
Дата: 18.02.08 09:31
Оценка:
Приветствую!
template <typename T>
class base
{
    T                    m_tData;
public:
    void                BaseFoo(void) const        { }
};

template <typename FinalClass>
class impl
{
    typedef FinalClass                        final_class;
public:
    void                Foo(void) const
    { static_cast<const final_class*>(this)->BaseFoo(); }
    void                Foo(void)
    { static_cast<final_class*>(this)->BaseFoo(); }
};

template <typename T>
class final
    : public base<T>
    , public impl< final<T> >
{
};
Чем порочна такая практика разработки дизайна? Говорит ли стандарт об этом что-нибудь?
Re: static_cast<final_class*>(this)
От: Аноним  
Дата: 18.02.08 09:57
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Приветствую!

А>
...
А>template <typename T>
А>class final
А>    : public base<T>
А>    , public impl< final<T> >
...
А>
Чем порочна такая практика разработки дизайна? Говорит ли стандарт об этом что-нибудь?


Вполне приемлимый способ наращивания класса. Но зачем тебе такие обёртки вызывов, и чем тебе обычное наследование и виртальные функции так не угодили?
Re: static_cast<final_class*>(this)
От: Аноним  
Дата: 18.02.08 10:09
Оценка:
Здравствуйте, Аноним, Вы писали:

А>
...
А>    void                Foo(void) const
А>    { static_cast<const final_class*>(this)->BaseFoo(); }
А>    void                Foo(void)
А>    { static_cast<final_class*>(this)->BaseFoo(); }
...
А>
Чем порочна такая практика разработки дизайна? Говорит ли стандарт об этом что-нибудь?

Чревато ошибками, и не допониманием со стороны окружающих
кстати this преобразуется не правильно.

Видимо имелось в виду что то такое:
struct base {
    int  x;
    void BaseFoo() { printf("x=%d\n",x); }
    base() : x(3) {}
};
template <class T> struct more {
    T* self() const { return (T*)((char*)this-sizeof(T)); }
    void Foo()      { Profiler p("Foo"); self()->BaseFoo();  }
};
struct final :  base,  more<base> {};
Re: static_cast<final_class*>(this)
От: Аноним  
Дата: 18.02.08 10:32
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Приветствую!

А>
А>template <typename T>
А>class base
А>{
А>    T                    m_tData;
А>public:
А>    void                BaseFoo(void) const        { }
А>};

А>template <typename FinalClass>
А>class impl
А>{
А>    typedef FinalClass                        final_class;
А>public:
А>    void                Foo(void) const
А>    { static_cast<const final_class*>(this)->BaseFoo(); }
А>    void                Foo(void)
А>    { static_cast<final_class*>(this)->BaseFoo(); }
А>};

А>template <typename T>
А>class final
А>    : public base<T>
А>    , public impl< final<T> >
А>{
А>};
А>
Чем порочна такая практика разработки дизайна? Говорит ли стандарт об этом что-нибудь?


А чем плох

final_class::BaseFoo()
Re: static_cast<final_class*>(this)
От: Аноним  
Дата: 18.02.08 10:39
Оценка:
Более развернутый вопрос:
template <typename T>
class base
{
    T                    m_tData;
public:
    base(void) : m_tData()                            { }
    void                BaseFoo(void) const            { }
};
class count
{
    int                    m_iCount;
public:
    count(void) : m_iCount()                        { }
    void                Inc(void)                    { ++m_iCount; }
    void                Dec(void)                    { --m_iCount; }
};

template <typename FinalClass>
class impl
{
    typedef FinalClass                                                final_class;
public:
    void                Foo(void) const
    { static_cast<const final_class*>(this)->BaseFoo(); }
    void                Foo(void)
    {
        static_cast<final_class*>(this)->Inc();
        static_cast<final_class*>(this)->BaseFoo();
        static_cast<final_class*>(this)->Dec();
    }
};

template <typename T>
class final
    : public base<T>
    , public count
    , public impl< final<T> >
{
};

    //const final<int>    obj;
    final<int>            obj;
    obj.Foo();
Re[2]: static_cast<final_class*>(this)
От: Аноним  
Дата: 18.02.08 10:44
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Более развернутый вопрос:

А>
А>template <typename T>
А>class base
А>{
А>    T                    m_tData;
А>public:
А>    base(void) : m_tData()                            { }
А>    void                BaseFoo(void) const            { }
А>};
А>class count
А>{
А>    int                    m_iCount;
А>public:
А>    count(void) : m_iCount()                        { }
А>    void                Inc(void)                    { ++m_iCount; }
А>    void                Dec(void)                    { --m_iCount; }
А>};

А>template <typename FinalClass>
А>class impl
А>{
А>    typedef FinalClass                                                final_class;
А>public:
А>    void                Foo(void) const
А>    { static_cast<const final_class*>(this)->BaseFoo(); }
А>    void                Foo(void)
А>    {
А>        static_cast<final_class*>(this)->Inc();
А>        static_cast<final_class*>(this)->BaseFoo();
А>        static_cast<final_class*>(this)->Dec();
А>    }
А>};

А>template <typename T>
А>class final
А>    : public base<T>
А>    , public count
А>    , public impl< final<T> >
А>{
А>};

А>    //const final<int>    obj;
А>    final<int>            obj;
А>    obj.Foo();
А>

Плохо только одно -- это будет работать не правильно. impl *this никакого отношения не имеет к final *this.
Учи мат часть
Re[3]: static_cast<final_class*>(this)
От: Аноним  
Дата: 18.02.08 10:48
Оценка:
Здравствуйте, Аноним, Вы писали:
А>impl *this никакого отношения не имеет к final *this.
Имеет, и самое прямое. final является наследником impl.
А>Учи мат часть
пересмотри приведенный мною код
Re[2]: static_cast<final_class*>(this)
От: Аноним  
Дата: 18.02.08 10:53
Оценка:
Здравствуйте, Аноним, Вы писали:

А>А чем плох


А>
А>final_class::BaseFoo()
А>

тем, что этот вызов годен лишь только в том случае, когда BaseFoo объявлена как static
Re: static_cast<final_class*>(this)
От: Qbit86 Кипр
Дата: 18.02.08 11:59
Оценка: 7 (1) +1 :))
Здравствуйте, Аноним, Вы писали:

А>Чем порочна такая практика разработки дизайна?


Такая практика дизайна порочна тем, что выровненный по табам код
1) расползается к чертям, если установлен другой размер табуляции;
2) трудно поддаётся модификации из-за необходимости поддерживать выравнивание.

А так код вполне нормальный, гуглить надо по запросам «CRTP», «Couriosly Recurring Template Pattern», плюс посмотреть в книжке Вандевурда, там тоже есть описание. CRTP является статическим аналогом паттерна Template Method.
Глаза у меня добрые, но рубашка — смирительная!
Re[2]: static_cast<final_class*>(this)
От: Аноним  
Дата: 18.02.08 13:03
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Здравствуйте, Аноним, Вы писали:


А>>Чем порочна такая практика разработки дизайна?


Q>Такая практика дизайна порочна тем, что выровненный по табам код

Q>1) расползается к чертям, если установлен другой размер табуляции;
подобная аргументировка ведет к флэйму, поэтому опустим ее, если не возражаешь...

Q>2) трудно поддаётся модификации из-за необходимости поддерживать выравнивание.

выравнивание чего? разве static_cast<...>() создан не для этого? речь, ведь, не идет о выравнивании как в этом посте — http://www.rsdn.ru/forum/message/2842291.1.aspx
Автор:
Дата: 18.02.08


Q>А так код вполне нормальный, гуглить надо по запросам «CRTP», «Couriosly Recurring Template Pattern», плюс посмотреть в книжке Вандевурда, там тоже есть описание. CRTP является статическим аналогом паттерна Template Method.

Уже смотрел... Хотелось узнать кто и как реализует дизайн классов в своих, промышленного типа, библиотеках.
Перелапатил кучу литературы и так и не смог определиться какой создать дизайн библиотеки. Реализовывать ли ее через идиому "является частью" или же "реализован как". Вот главный вопрос данного поста!
Конечно же, я понимаю, что все зависит от частностей. Поэтому хотелось услышать аргументы в пользу той или иной идиомы, именно в сфере промышленной разработки библиотеки. Каковы были предпосылки к выбору дизайна классов?
Re[3]: static_cast<final_class*>(this)
От: Qbit86 Кипр
Дата: 18.02.08 13:18
Оценка:
Здравствуйте, Аноним, Вы писали:

А>подобная аргументировка ведет к флэйму, поэтому опустим ее, если не возражаешь...


Не-не, не возражаю!

А>выравнивание чего?


Я имел в виду в этом смысле.

А>Конечно же, я понимаю, что все зависит от частностей. Поэтому хотелось услышать аргументы в пользу той или иной идиомы, именно в сфере промышленной разработки библиотеки. Каковы были предпосылки к выбору дизайна классов?


CRTP — это скорее не дизайн классов, а приём, паттерн. Некоторые use cases перечислены в одном старом блоге.

Мне очень редко приходилось пользоваться таким паттерном, раза три всего.

А>Уже смотрел... Хотелось узнать кто и как реализует дизайн классов в своих, промышленного типа, библиотеках.


Ну, в Boost CRTP используется очень широко. Но этот паттерн больше нужен библиотекописателям, реже прикладникам.
Глаза у меня добрые, но рубашка — смирительная!
Re[4]: static_cast<final_class*>(this)
От: Qbit86 Кипр
Дата: 18.02.08 13:23
Оценка:
Q>Мне очень редко приходилось пользоваться таким паттерном, раза три всего.

Имеется в виду, редко приходилось реализовывать. А пользоваться приходится чаще, в рамках использования Boost и Loki.
Глаза у меня добрые, но рубашка — смирительная!
Re[5]: static_cast<final_class*>(this)
От: Аноним  
Дата: 18.02.08 13:44
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>>Мне очень редко приходилось пользоваться таким паттерном, раза три всего.


Q>Имеется в виду, редко приходилось реализовывать. А пользоваться приходится чаще, в рамках использования Boost и Loki.

Парадокс заключается в том, что Саттер и Мейерс рекомендуют использовать идиому "реализован как", а Александреску просто добивает своим SmartPtr сомневающихся в этом. Вместе с этим, паттерн CRTP широко используется в таких библиотеках как WTL(практически повсеместно) и stl(в меньшей степени).
Re: вопрос к знатокам от телезрителей
От: Аноним  
Дата: 18.02.08 14:36
Оценка:
во что выливается, с точки зрения производительности, вызов функций Foo, на том или ином компиляторе(в большей степени меня интересует EVC4, CodeWarrior for Symbian OS, VC6.0-8.0):
struct base
{
    void                BaseFoo(void)        { }
};
template < typename FinalClass >
struct impl
{
    void                Foo(void)
    { static_cast<FinalClass*>(this)->BaseFoo(); }
};
struct  final : public base, public impl< final >
{
};

struct base
{
};
template < typename Base >
struct impl
{
    static void            Foo(Base* pBase)    { }
};
template < typename Impl >
struct  final : public base
{
    void                Foo(void)            { Impl::Foo(this); }
};

struct base
{
    void                Foo(void)            { }
};
template < typename Base >
struct final
{
    Base*                pBase;
    void                Foo(void)            { pBase->Foo(this); }
};
Re[6]: static_cast<final_class*>(this)
От: Qbit86 Кипр
Дата: 18.02.08 14:42
Оценка:
Здравствуйте, Аноним, Вы писали:

A>Реализовывать ли ее через идиому "является частью" или же "реализован как". Вот главный вопрос данного поста!


Это скорее ортогональные, а не взаимоисключающие понятия. «Реализован посредством» (IIITO — is implemented in terms of) может быть воплощён через «содержит» или через приватное наследование.

А>Парадокс заключается в том, что Саттер и Мейерс рекомендуют использовать идиому "реализован как", а Александреску просто добивает своим SmartPtr сомневающихся в этом. Вместе с этим, паттерн CRTP широко используется в таких библиотеках как WTL(практически повсеместно) и stl(в меньшей степени).


Никакого парадокса нет. Не стоит рассматривать публичное наследование при реализации CRTP как попирание принципа «Предпочитайте композицию наследованию при отношении IIITO». Просто паттерн такой.
Глаза у меня добрые, но рубашка — смирительная!
Re: static_cast<final_class*>(this)
От: vopl Россия  
Дата: 18.02.08 15:12
Оценка:
Здравствуйте, Аноним, Вы писали:

А>...

здесь
Автор:
Дата: 26.10.07
проблемы msvc7.1 в некоторых случаях совмещения шаблонных классов в одной иерархии множественным наследованием
Re[2]: static_cast<final_class*>(this)
От: Аноним  
Дата: 18.02.08 15:29
Оценка:
Здравствуйте, vopl, Вы писали:

V>Здравствуйте, Аноним, Вы писали:


А>>...

V>здесь
Автор:
Дата: 26.10.07
проблемы msvc7.1 в некоторых случаях совмещения шаблонных классов в одной иерархии множественным наследованием

так глубоко пока еще не копал(требования к библиотеке таковы, что необходимо создать терминальные классы, пока)...
так, что пост уже настораживает, относительно применения CRTP///
Спасибо!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.