Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Указатель на метод


Автор: Lazin 21.7.2008, 11:42
В общем есть шаблон класса, получающий 2 параметра, тип владельца - Owner, и указатель на метод владельца - callback
Код

template<
    class Owner,
    void (Owner::*callback)( connection<Owner, callback>& )
>
class connection
{
    Owner owner_;
public:
    connection(Owner& o) : owner_(o) {}

    void do_work()
    {
        (owner.*callback)(*this);
    }
};

проблема в том, что callback должен получать ссылку на connection... так по крайней мере задумано smile , но это не работает... в общем нужен какой-то workaround...

Автор: xvr 21.7.2008, 11:54
Цитата(Lazin @ 21.7.2008,  11:42)
В общем есть шаблон класса, получающий 2 параметра, тип владельца - Owner, и указатель на метод владельца - callback
Код

template<
    class Owner,
    void (Owner::*callback)( connection<Owner, callback>& )
>
class connection
{
    Owner owner_;
public:
    connection(Owner& o) : owner_(o) {}

    void do_work()
    {
        (owner.*callback)(*this);
    }
};

проблема в том, что callback должен получать ссылку на connection... так по крайней мере задумано smile , но это не работает... в общем нужен какой-то workaround...

У тебя в типе параметра callback'а получается бесконечная рекурсия. Нельзя ли сделать какой нибудь базовый класс для connection (не темплейтный вообще или по крайней мере без типа самого callback'а в параметрах темплейта) и передавать именно его в параметре callback'а ?

Автор: Lazin 21.7.2008, 12:04
тогда уж  проще обойтись наследованием... smile 

Автор: Ulysses4j 21.7.2008, 12:14
Может, можно обойтись так:
Код
template<
    typename Owner,
    typename Conn,
    void (Owner::*callback)( Conn& )
>
class connection
{
    Owner owner_;
public:
    connection(Owner& o) : owner_(o) {}

    void do_work()
    {
        (owner_.*callback)(*this);
    }
};


Автор: Lazin 21.7.2008, 12:31
Цитата(Ulysses4j @  21.7.2008,  12:14 Найти цитируемый пост)
Может, можно обойтись так:

так сделать можно, но тогда клиент сможет передать любой callback, что не очень хорошо...

Автор: Lycifer 21.7.2008, 12:50
Почему в конструктор нельзя передать?

Цитата

Цитата(Ulysses4j @  21.7.2008,  12:14 Найти цитируемый пост)
Может, можно обойтись так:

так сделать можно, но тогда клиент сможет передать любой callback, что не очень хорошо... 

А если typeid использовать, ну и кидать исключения(разрушать объект)?

Автор: Lazin 21.7.2008, 12:57
Цитата(Lycifer @  21.7.2008,  12:50 Найти цитируемый пост)
Почему в конструктор нельзя передать?

потому-что тип заранее не известен, класс должен работать с некоторым типом, и некоторым его методом, получающим ссылку на connection

Добавлено @ 13:01
Цитата(Ulysses4j @ 21.7.2008,  12:14)
Может, можно обойтись так:
Код
template<
    typename Owner,
    typename Conn,
    void (Owner::*callback)( Conn& )
>
class connection
{
    Owner owner_;
public:
    connection(Owner& o) : owner_(o) {}

    void do_work()
    {
        (owner_.*callback)(*this);
    }
};

как выяснилось нельзя, так как теперь, что-бы инстанцировать шаблон, нужно написать что-то вроде


Код

template<
    class Owner,
    class Param,
    void (Owner::*callback)( Param& )
>
class connection
{
    Owner owner_;
public:
    connection(Owner& o) : owner_(o) {}

    void do_work()
    {
        (owner.*callback)(*this);
    }
};

class client
{
    typedef connection<client, connection<client, ..!!WTF!!.., &client::do_work>, &client::do_work> connect;
......


Автор: Ulysses4j 21.7.2008, 13:35
Да, действительно, тогда предлагаю не мучиться с нешаблонным параметром шаблона, а перетащить этот указатель на член в рантайм. Как предложил Lycifer:
Код
template<typename Owner>
class connection {
    typedef void (Owner::*CallbackT) (connection<Owner>&);

    Owner owner_;

    CallbackT callback_;

public:
    connection(Owner& o, CallbackT callback) : owner_(o), callback_(callback) {}

    void do_work() {
        (owner_.*callback_)(*this);
    }
};

class Client {
public:
    void do_work(connection<Client>& ) {}
};

int main() {
    Client cl;
    connection<Client> con(cl, &Client::do_work);
    con.do_work();
}

Автор: Lazin 21.7.2008, 16:06
в общем переписал по другому, теперь у меня callback поучает хэш, а не указатель на вызвавший объект, а по хэшу уже определяется объект... как-то так smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)