gpt4 book ai didi

boost::asio::basic_socket_acceptor::async_accept() 的接受处理程序中的 C++ boost::asio Variadic 模板运算符

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:07:35 25 4
gpt4 key购买 nike

我正在尝试创建一个接受连接的异步 TCP 服务器。我将要使用如下所示的接受处理程序函数对象:

template <typename Function>
struct callback
{
Function func_;

callback()
{
}

callback(Function&& f)
: func_(std::forward<Function>(f))
{
}

template <typename ...Args>
void operator() (Args&& ...args)
{
func_(std::forward<Args>(args)...);
}
};

我的服务器类:

#include <boost/bind.hpp>
#include <boost/asio.hpp>

#include <session.hpp>
#include <handler.hpp>
class server
{
private:
typedef callback<boost::function<void(const boost::system::error_code&, session_ptr&)>> accept_handler;

boost::asio::io_service& io_service_;
tcp::acceptor acceptor_;
accept_handler handler_;

public:
server(boost::asio::io_service& io_service, short port)
: io_service_(io_service),
acceptor_(io_service, tcp::endpoint(tcp::v4(), port))
{
session_ptr new_session = session_ptr(new session(io_service_));
auto callback = boost::bind(&server::handle_accept,
this,
boost::asio::placeholders::error,
new_session);

handler_ = accept_handler(std::move(callback));


acceptor_.async_accept(new_session->socket(),
handler_);
}

void handle_accept(const boost::system::error_code& error, session_ptr new_session)
{
if (!error)
{
new_session->start();
new_session.reset(new session(io_service_));

acceptor_.async_accept(new_session->socket(),
handler_);

}
}
};

但是当我尝试编译时出现以下错误:

错误:对“(boost::function&)>) (const boost::system::error_code&)”的调用不匹配 func_(std::forward(args)...);

所以我必须只使用满足 AcceptHandler 要求的处理程序

struct accept_handler
{
...
void operator()(
const boost::system::error_code& ec)
{
...
}
...
};

或者有使用重载可变参数模板 opreator() 的解决方案?

最佳答案

UPDATED After realizing the real mistake:

好消息是:只需更改一行即可轻松修复错误:

typedef callback<boost::function<void(const boost::system::error_code&, session_ptr&)>> accept_handler;

进入

typedef callback<boost::function<void(const boost::system::error_code&)>> accept_handler;

由于各种原因,先前的定义完全是错误的:

  • 不符合处理程序要求
  • 它也不匹配 bind表达式:bind(&server::handle_accept, this, asio::placeholders::error, new_session) .请注意,它只有 1 个占位符 ( asio::placeholders::error ),因此它不可能使用 2 个参数

Live On Coliru

#include <boost/function.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>

namespace ba = boost::asio;
using ba::ip::tcp;

struct session : std::enable_shared_from_this<session> {
session(ba::io_service& svc) : _socket(svc) {}

void start() {} // do something asynchronously
tcp::socket& socket() { return _socket; }

tcp::socket _socket;
};

using session_ptr = std::shared_ptr<session>;

template <typename Function>
struct callback
{
Function func_;

callback(Function&& f = {}) : func_(std::forward<Function>(f)) {
}

template <typename ...Args>
void operator() (Args&& ...args) {
func_(std::forward<Args>(args)...);
}
};

class server
{
private:
typedef callback<boost::function<void(const boost::system::error_code&)>> accept_handler;

ba::io_service& io_service_;
tcp::acceptor acceptor_;
accept_handler handler_;

public:
server(ba::io_service& io_service, short port)
: io_service_(io_service),
acceptor_(io_service, tcp::endpoint(tcp::v4(), port))
{
session_ptr new_session = session_ptr(new session(io_service_));
handler_ = accept_handler(bind(&server::handle_accept, this, ba::placeholders::error, new_session));

acceptor_.async_accept(new_session->socket(), handler_);
}

void handle_accept(const boost::system::error_code& error, session_ptr new_session)
{
if (!error)
{
new_session->start();
new_session.reset(new session(io_service_));

acceptor_.async_accept(new_session->socket(),
handler_);

}
}
};

int main() {
}

简化:删除冗余包装

我在这里唯一要注意的是,非常清楚,没有 callback<> , accept_handler有什么用:

Live On Coliru

class server
{
private:
ba::io_service& io_service_;
tcp::acceptor acceptor_;

public:
server(ba::io_service& io_service, short port)
: io_service_(io_service),
acceptor_(io_service, tcp::endpoint(tcp::v4(), port))
{
do_accept();
}

void do_accept() {
session_ptr new_session = session_ptr(new session(io_service_));
acceptor_.async_accept(new_session->socket(), bind(&server::handle_accept, this, ba::placeholders::error, new_session));
}

void handle_accept(const boost::system::error_code& error, session_ptr new_session)
{
if (!error) {
new_session->start();
do_accept();
}
}
};

更简单:捕获 Lambda

您可以不使用绑定(bind)、占位符、handle_accept。同时加入:

Live On Coliru

class server
{
private:
ba::io_service& io_service_;
tcp::acceptor acceptor_;

public:
server(ba::io_service& io_service, short port)
: io_service_(io_service),
acceptor_(io_service, tcp::endpoint(tcp::v4(), port))
{
do_accept();
}

void do_accept() {
session_ptr new_session = std::make_shared<session>(io_service_);

acceptor_.async_accept(new_session->socket(), [this,new_session](const boost::system::error_code& error) {
if (!error) {
new_session->start();
do_accept();
}
});
}
};

旧答案

在第一次阅读时,我假设您遇到了我在使用 Boost Asio 和多​​态 lambda 时经常遇到的经典陷阱。对不起。

确实,在可变参数的情况下,概念检查无法验证处理程序要求。我的方法是禁用需求检查:

#define BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS 1

主要丢失的是不匹配时更友好的错误消息:

Asio 1.6.0 / Boost 1.47

  • Added friendlier compiler errors for when a completion handler does not meet the necessary type requirements. When C++0x is available (currently supported for g++ 4.5 or later, and MSVC 10), static_assert is also used to generate an informative error message. This checking may be disabled by defining BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS.

参见 http://www.boost.org/doc/libs/1_65_1/doc/html/boost_asio/history.html

关于boost::asio::basic_socket_acceptor::async_accept() 的接受处理程序中的 C++ boost::asio Variadic 模板运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47232234/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com