Re[5]: Шаблонная функция как генератор переменных
От: Кодт Россия  
Дата: 28.08.07 15:33
Оценка:
Здравствуйте, unreg_flex, Вы писали:

_>Приведу код, надеюсь так будет понятней:

Вот за это спасибо.


_>typedef bool (Manager::*Listener)(double data);

_>class Manager {

_>public:

_>  void AddListener(int nSlot,Listener pListener) {
_>    // тут производится добавление pListener в некоторый список
_>    ...
_>  }
_>}

_>Этот класс менять нельзя.

Я так понимаю, в "некоторый список" добавляется пара (this,SomeMemberFunc)?
В противном случае это заподлянка: колбек-функция без пользовательского параметра.

_>Но хочется добавить в класс производный от Manager несколько методов, которые будут автоматически

_>генерировать некорые часто используемые типы Listener-ов (дабы не писать их каждый раз ручками),
_>например так:
_>
_>class CoolManager: public Manager {

_>public:

_>  template< class Object >
_>  void AddCoolListener(int nSlot,Object *pObject) {
_>    Manager::AddListener(nSlot,&CoolManager::CoolListener< Object >);
_>  }

Не получится.
Указатели на объекты — ковариантны (указатель на наследника приводится к указателю на базу), а указатели на члены — контравариантны (указатель на член базы приводится к указателю на член наследника).
class Base
{
    .....
    void bbb();
};
class Derived : public Base
{
    .....
    void ddd();
};

void play_bm(void (Base::*f)())    { Base b; (b.*f)(); }
void play_dm(void (Derived::*f)()) { Derived d; (d.*f)(); }

void play_br(Base& b) { p.bbb(); }
void play_dr(Derived& d) { d.ddd(); }

int main()
{
    // контравариантность членов
    play_br(&Derived::ddd); // если бы скомпилировалось, то получим b.ddd() и вылетим
    play_dr(&Base::bbb); // d.bbb() - всё законно, член bbb унаследован
    
    // ковариантность объектов
    Base b; play_dr(b); // если бы скомпилировалось, то получим b.ddd()
    Derived d; play_br(d); // d.bbb()
}



Давай, показывай полностью объявление класса Manager. Будем искать точки кастомизации.

К>>О, кстати! Пришла в голову идея хака, действующего глобально. Точнее, обеспечивающего независимость между единицами трансляции.


_>Вот за это +3, хоть проблему это не решает (есть макросы), но это интересный способ увеличить диапазон действия __COUNTER__.

_>Вроде просто, но сам я не догадался
_>Кстати, а почему это хак???

Потому что эта штука, хотя и легальна, но отлично работает лишь в узких рамках.
Покуда все объекты в рантайме можно уникально идентифицировать местом в исходниках, где они создаются — всё работает.
Добавляем циклы, повторные вызовы, косвенность — до свидания.
И главное, что ты это не диагностируешь, пока не подорвёшься на нарушении логики работы.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.