Как использовать enable_shared_from_this в шаблонных функциях? - PullRequest
1 голос
/ 29 февраля 2020

Я пытаюсь использовать функцию std :: enabled_shared_from_this в шаблонной функции, но я получаю сообщение об ошибке bad_weak_ptr при вызове shared_from_this () в классе.

template<T>
class A: public std::enable_shared_from_this <A<T>>
{

    /* some parts in the class */
    void Run()
    {
        resolver_.async_resolve(host_, port_, boost::bind_front_handler(&A:on_resolve, this->shared_from_this());
    }
    /* ... */
};

Я пробовал std :: enable_shared_from_this> :: shared_from_this () и this-> shared_from_this (), и я не вызывал функцию shared_from_this () в конструкторе классов. Если есть какие-либо способы решить эту ошибку, пожалуйста, дайте мне знать.

1 Ответ

3 голосов
/ 29 февраля 2020

Ваш запрос неверен, вы передаете слишком много аргументов . Вместо этого передайте один параметр запроса:

    boost::asio::ip::tcp::resolver::query q{host_, port_};
    resolver_.async_resolve(q,

Далее вы можете использовать любой предпочитаемый вами метод связывания:

    boost::bind(&A::on_resolve, this->shared_from_this(),
        boost::asio::placeholders::error(),
        boost::asio::placeholders::results())

Или вообще не использовать связывание:

    resolver_.async_resolve(q,
        [self=this->shared_from_this()](boost::system::error_code ec, boost::asio::ip::tcp::resolver::results_type eps) {
            self->on_resolve(ec, eps);
        }
    );

Или с помощью вспомогательного помощника от Beast:

    boost::beast::bind_front_handler(&A::on_resolve, this->shared_from_this())

Демонстрация в реальном времени

Live On Coliru

#include <memory> // for std::shared_from_this etc
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>                    // for boost::bind
#include <boost/beast/core/bind_handler.hpp> // for bind_front_handler

template<typename T>
class A: public std::enable_shared_from_this<A<T>>
{
  public:
    A(boost::asio::io_context& io, std::string host, std::string port)
        : resolver_(io), host_(host), port_(port) {}

    void Run()
    {
        boost::asio::ip::tcp::resolver::query q{host_, port_};
        resolver_.async_resolve(q,
            boost::beast::bind_front_handler(&A::on_resolve, this->shared_from_this())
        );
        resolver_.async_resolve(q,
            boost::bind(&A::on_resolve, this->shared_from_this(),
                boost::asio::placeholders::error(),
                boost::asio::placeholders::results())
        );
        resolver_.async_resolve(q,
            [self=this->shared_from_this()](boost::system::error_code ec, boost::asio::ip::tcp::resolver::results_type eps) {
                self->on_resolve(ec, eps);
            }
        );
    }

  private:
    void on_resolve(boost::system::error_code ec, boost::asio::ip::tcp::resolver::results_type eps) {
        std::cout << "Resolved: (" << ec.message() << "):";
        for (auto& ep : eps) {
            std::cout << " " << ep.endpoint();
        }
        std::cout << "\n";
    }

    boost::asio::ip::tcp::resolver resolver_;
    std::string host_, port_;
};

int main() {
    boost::asio::io_context io;
    auto instance = std::make_shared<A<int> >(io, "localhost", "1234");
    instance->Run();

    io.run();
}

Печать (не на Coliru из-за сетевых ограничений):

Resolved: (Success): 127.0.0.1:1234
Resolved: (Success): 127.0.0.1:1234
Resolved: (Success): 127.0.0.1:1234
...