переменная-член функции шаблона - PullRequest
0 голосов
/ 04 декабря 2018

Мое намерение состоит в том, чтобы спроектировать модель обратного вызова события в сети связи, обратный вызов события включает в себя «recv, send, accept, shutdown ...»

class client
{
public:
    template<typename F1>
    void bind_recv(F1 && f)
    {
        // How to save the parameter of bind_recv function in _recv_callback member variable ?
        _recv_callback = f;
    }
    // bind_send
    // bind_accept
    // bind_shutdown
    // ...

protected:
    void notify_recv()
    {
        _recv_callback();
    }
    // notify_send
    // ...

    // How to declare the type of these variable ?
    F1 _recv_callback;
    // F2 _send_callback;
    // ...
};

int main()
{
    client c;
    c.bind_recv([](uint8_t * data, size_t len)
    {

    });


    return(0);
}

Мне нужно сохранить обратные вызовы и вызвать их нав нужный момент, но параметры каждой функции обратного вызова различны, так как я могу их сохранить?

Я думаю, может быть, мое мышление неверно, так как я могу изменить дизайн, чтобы удовлетворить это требование?

1 Ответ

0 голосов
/ 04 декабря 2018

Вы не можете объявить переменные-члены шаблона.Но даже если вы могли бы объявить _recv_callback с типом шаблона F1, F1 должен быть определен во время компиляции.Так что же будет с оператором присваивания в client::bind_recv

 _recv_callback = f;

, когда переданный параметр f не относится к типу _recv_callback?

Даже если вы можетеопределите оператор присвоения для _recv_callback, который допускает различные типы для правой стороны, вы можете «потерять» некоторую информацию.В частности, после назначения вы больше не знаете, какой тип был f.И что еще хуже, f мог иметь некоторые дополнительные переменные-члены, которые вы не можете сохранить в _recv_callback.

. Решение этих проблем состоит в том, чтобы сначала определить общий «базовый» (возможно, абстрактный) классразрешенный параметр f для передачи client::bind_recv.Затем вы используете полиморфизм для лечения разных случаев.Пример:

#include <memory>    

class callback {

// Some purely virtual functions for a generic interface
virtual ~callback { }
};

class recv_callback : callback {
// Specific implementations of pure virtual members declared in callback
virtual recv_callback;
};

class client
{
public:
    void bind_recv(callback *f)
    {
        _recv_callback.reset(f);
    }

protected:

    std::unique_ptr<callback> _recv_callback;

}

Передав указатель на client::bind_recv, вы избегаете проблемы незнания того, как обрабатывать неизвестный тип f: вам нужно передать уже выделенный объект.Также обратите внимание, что я использовал умный указатель для _recv_callback, чтобы не допустить утечки памяти.

...