std::bind 参数与函数参数不匹配?
std::bind arguments not matching function parameters?
我正在尝试通过连接握手传递套接字,并使用 std::bind
来实现。我遇到的编译问题(在一个连续的块中,为了便于阅读,我添加了空格)是:
'std::_Bind<_Functor(_Bound_args ...)>::_Bind(_Functor&&, _Args&& ...)
[with _Args = {socket_state**, std::function<void(socket_state*)>&, boost::asio::basic_socket_acceptor<boost::asio::ip::tcp, boost::asio::executor>&, boost::asio::io_context&};
_Functor = void (*)(socket_state*, std::function<void(socket_state*)>&, boost::asio::basic_socket_acceptor<boost::asio::ip::tcp>&, boost::asio::io_context&);
_Bound_args = {socket_state**, std::function<void(socket_state*)>, boost::asio::basic_socket_acceptor<boost::asio::ip::tcp, boost::asio::executor>, boost::asio::io_context}]':
我的代码如下,错误似乎在给 boost::asio::acceptor.async_accept(socket, ...)
的 std::bind
参数和 accept_new_client
方法
的参数上唠叨
void start_server(std::function<void(socket_state*)>& func, tcp::acceptor& acceptor, boost::asio::io_context& context)
{
acceptor.listen();
// Start client connection loop
networking::wait_for_client(func, acceptor, context);
}
void wait_for_client(std::function<void(socket_state*)>& func, tcp::acceptor& acceptor, boost::asio::io_context& context)
{
boost::asio::ip::tcp::socket socket(context);
// socket_state is its own class which links a particular socket with an ID and buffer data
// it also holds a function to indicate which part of the connection handshake it needs to go to next
socket_state* state = new socket_state(func, &socket);
acceptor.async_accept(socket, std::bind(&networking::accept_new_client, state, func, acceptor, context));
}
void accept_new_client(socket_state* state, std::function<void(socket_state*)>& func, tcp::acceptor& acceptor, boost::asio::io_context& context)
{
state->on_network_action(state);
wait_for_client(func, acceptor, context);
}
看起来它们会匹配,但您可以看到错误状态我的 std::bind
参数是 socket_state**
而不是 socket_state*
,并且 boost::asio::basic_socket_acceptor<boost::asio::ip::tcp, boost::asio::executor>&
而不是 boost::asio::basic_socket_acceptor<boost::asio::ip::tcp>&
.
我不知道“with _Args”和“_Bound_args”是什么。
这段代码有很多问题。
共享指针似乎处于错误的抽象级别。您可能希望整个“连接”类型都具有共享生命周期,而不仅仅是套接字。在你的情况下,socket_state
是一个很好的候选人。
无论如何,您的套接字是一个局部变量,您将一个过时的指针传递给内部 socket_state
。套接字状态看起来一定会被泄露。
所以这永远行不通。
接下来,绑定正在热切地绑定所有参数,留下空签名。这不是 any overload 接受的 [没有双关语]。你需要匹配
让我们使用 AcceptHandler。另外,我们不要绑定所有冗余参数(func
已经在 socket_stateremember,
io_context` 中过度共享等)。
总的来说,您似乎需要建立信心来了解您所在的州。例如。这一行是有症状的:
state->on_network_action(state);
因为 on_network_action
是 socket_state
的成员函数,所以永远不需要将 state
作为参数传递(它将是 this
隐式) . acceptor
和 contest
在所有情况下都是一样的。
演示
修复以上所有问题,使用 std::shared_ptr 和绑定(你已经做了),注意 placeholder::_1
接受 error_code 等)
#include <boost/asio.hpp>
#include <memory>
#include <iostream>
namespace ba = boost::asio;
using namespace std::chrono_literals;
using boost::system::error_code;
using ba::ip::tcp;
struct socket_state;
using Callback = std::function<void(socket_state&)>;
struct socket_state : std::enable_shared_from_this<socket_state> {
Callback _callback;
tcp::socket _socket;
template <typename Executor>
socket_state(Callback cb, Executor ex) : _callback(cb)
, _socket(ex)
{
}
void on_network_action() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
struct networking {
using StatePtr = std::shared_ptr<socket_state>;
explicit networking(ba::io_context& ctx, Callback callback)
: context(ctx)
, callback(callback)
{
}
ba::io_context& context;
tcp::acceptor acceptor {context, {{}, 8989}};
Callback callback;
void start_server()
{
std::cout << "start_server" << std::endl;
acceptor.listen();
wait_for_client(); // Start client connection loop
}
void stop_server() {
std::cout << "stop_server" << std::endl;
acceptor.cancel();
acceptor.close();
}
void wait_for_client()
{
std::cout << "wait_for_client" << std::endl;
// socket_state is its own class which links a particular socket with
// an ID and buffer data it also holds a function to indicate which
// part of the connection handshake it needs to go to next
auto state =
std::make_shared<socket_state>(callback, context.get_executor());
acceptor.async_accept(state->_socket,
std::bind(&networking::accept_new_client, this,
std::placeholders::_1, state));
}
void accept_new_client(error_code ec, StatePtr state)
{
if (ec) {
std::cout << "accept_new_client " << ec.message() << std::endl;
return;
}
std::cout << "accept_new_client " << state->_socket.remote_endpoint()
<< std::endl;
state->on_network_action();
wait_for_client();
}
};
int main() {
ba::io_context ctx;
networking server(ctx, [](socket_state&) {
std::cout << "This is our callback" << std::endl;
});
server.start_server();
ctx.run_for(5s);
server.stop_server();
ctx.run();
}
有一些随机连接:
start_server
wait_for_client
accept_new_client 127.0.0.1:54376
void socket_state::on_network_action()
wait_for_client
accept_new_client 127.0.0.1:54378
void socket_state::on_network_action()
wait_for_client
accept_new_client 127.0.0.1:54380
void socket_state::on_network_action()
wait_for_client
accept_new_client 127.0.0.1:54382
void socket_state::on_network_action()
wait_for_client
stop_server
accept_new_client Operation canceled
注意是版本做评论
// socket_state is its own class which links a particular socket with
// an ID and buffer data it also holds a function to indicate which
// part of the connection handshake it needs to go to next
不再是完整的谎言:)
我正在尝试通过连接握手传递套接字,并使用 std::bind
来实现。我遇到的编译问题(在一个连续的块中,为了便于阅读,我添加了空格)是:
'std::_Bind<_Functor(_Bound_args ...)>::_Bind(_Functor&&, _Args&& ...)
[with _Args = {socket_state**, std::function<void(socket_state*)>&, boost::asio::basic_socket_acceptor<boost::asio::ip::tcp, boost::asio::executor>&, boost::asio::io_context&};
_Functor = void (*)(socket_state*, std::function<void(socket_state*)>&, boost::asio::basic_socket_acceptor<boost::asio::ip::tcp>&, boost::asio::io_context&);
_Bound_args = {socket_state**, std::function<void(socket_state*)>, boost::asio::basic_socket_acceptor<boost::asio::ip::tcp, boost::asio::executor>, boost::asio::io_context}]':
我的代码如下,错误似乎在给 boost::asio::acceptor.async_accept(socket, ...)
的 std::bind
参数和 accept_new_client
方法
void start_server(std::function<void(socket_state*)>& func, tcp::acceptor& acceptor, boost::asio::io_context& context)
{
acceptor.listen();
// Start client connection loop
networking::wait_for_client(func, acceptor, context);
}
void wait_for_client(std::function<void(socket_state*)>& func, tcp::acceptor& acceptor, boost::asio::io_context& context)
{
boost::asio::ip::tcp::socket socket(context);
// socket_state is its own class which links a particular socket with an ID and buffer data
// it also holds a function to indicate which part of the connection handshake it needs to go to next
socket_state* state = new socket_state(func, &socket);
acceptor.async_accept(socket, std::bind(&networking::accept_new_client, state, func, acceptor, context));
}
void accept_new_client(socket_state* state, std::function<void(socket_state*)>& func, tcp::acceptor& acceptor, boost::asio::io_context& context)
{
state->on_network_action(state);
wait_for_client(func, acceptor, context);
}
看起来它们会匹配,但您可以看到错误状态我的 std::bind
参数是 socket_state**
而不是 socket_state*
,并且 boost::asio::basic_socket_acceptor<boost::asio::ip::tcp, boost::asio::executor>&
而不是 boost::asio::basic_socket_acceptor<boost::asio::ip::tcp>&
.
我不知道“with _Args”和“_Bound_args”是什么。
这段代码有很多问题。
共享指针似乎处于错误的抽象级别。您可能希望整个“连接”类型都具有共享生命周期,而不仅仅是套接字。在你的情况下,socket_state
是一个很好的候选人。
无论如何,您的套接字是一个局部变量,您将一个过时的指针传递给内部 socket_state
。套接字状态看起来一定会被泄露。
所以这永远行不通。
接下来,绑定正在热切地绑定所有参数,留下空签名。这不是 any overload 接受的 [没有双关语]。你需要匹配
让我们使用 AcceptHandler。另外,我们不要绑定所有冗余参数(func
已经在 socket_stateremember,
io_context` 中过度共享等)。
总的来说,您似乎需要建立信心来了解您所在的州。例如。这一行是有症状的:
state->on_network_action(state);
因为 on_network_action
是 socket_state
的成员函数,所以永远不需要将 state
作为参数传递(它将是 this
隐式) . acceptor
和 contest
在所有情况下都是一样的。
演示
修复以上所有问题,使用 std::shared_ptr 和绑定(你已经做了),注意 placeholder::_1
接受 error_code 等)
#include <boost/asio.hpp>
#include <memory>
#include <iostream>
namespace ba = boost::asio;
using namespace std::chrono_literals;
using boost::system::error_code;
using ba::ip::tcp;
struct socket_state;
using Callback = std::function<void(socket_state&)>;
struct socket_state : std::enable_shared_from_this<socket_state> {
Callback _callback;
tcp::socket _socket;
template <typename Executor>
socket_state(Callback cb, Executor ex) : _callback(cb)
, _socket(ex)
{
}
void on_network_action() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
struct networking {
using StatePtr = std::shared_ptr<socket_state>;
explicit networking(ba::io_context& ctx, Callback callback)
: context(ctx)
, callback(callback)
{
}
ba::io_context& context;
tcp::acceptor acceptor {context, {{}, 8989}};
Callback callback;
void start_server()
{
std::cout << "start_server" << std::endl;
acceptor.listen();
wait_for_client(); // Start client connection loop
}
void stop_server() {
std::cout << "stop_server" << std::endl;
acceptor.cancel();
acceptor.close();
}
void wait_for_client()
{
std::cout << "wait_for_client" << std::endl;
// socket_state is its own class which links a particular socket with
// an ID and buffer data it also holds a function to indicate which
// part of the connection handshake it needs to go to next
auto state =
std::make_shared<socket_state>(callback, context.get_executor());
acceptor.async_accept(state->_socket,
std::bind(&networking::accept_new_client, this,
std::placeholders::_1, state));
}
void accept_new_client(error_code ec, StatePtr state)
{
if (ec) {
std::cout << "accept_new_client " << ec.message() << std::endl;
return;
}
std::cout << "accept_new_client " << state->_socket.remote_endpoint()
<< std::endl;
state->on_network_action();
wait_for_client();
}
};
int main() {
ba::io_context ctx;
networking server(ctx, [](socket_state&) {
std::cout << "This is our callback" << std::endl;
});
server.start_server();
ctx.run_for(5s);
server.stop_server();
ctx.run();
}
有一些随机连接:
start_server
wait_for_client
accept_new_client 127.0.0.1:54376
void socket_state::on_network_action()
wait_for_client
accept_new_client 127.0.0.1:54378
void socket_state::on_network_action()
wait_for_client
accept_new_client 127.0.0.1:54380
void socket_state::on_network_action()
wait_for_client
accept_new_client 127.0.0.1:54382
void socket_state::on_network_action()
wait_for_client
stop_server
accept_new_client Operation canceled
注意是版本做评论
// socket_state is its own class which links a particular socket with
// an ID and buffer data it also holds a function to indicate which
// part of the connection handshake it needs to go to next
不再是完整的谎言:)