将 std::bind 应用于带有参数 <boost::asio::ip::tcp::socket> 的函数时出错?
Posted
技术标签:
【中文标题】将 std::bind 应用于带有参数 <boost::asio::ip::tcp::socket> 的函数时出错?【英文标题】:Error while appling std::bind to function with argument <boost::asio::ip::tcp::socket>? 【发布时间】:2018-05-20 08:35:09 【问题描述】:有一个函数接受 boost::asio::ip::tcp::socket
类型的参数。但我未能将 std::bind 应用于它。我检查了 std::_Bind_helper 中的模板参数,但没有发现问题。我已经尝试过 gcc 8.1.0 和 clang 6.0.0,它们给出了相同的错误。
#include <functional>
#include <boost/asio.hpp>
using namespace std;
namespace asio = boost::asio;
using tcp = asio::ip::tcp;
int c;
void good_f(int) c=1;
void good()
using typeA = int;
auto helper = std::bind(&good_f, typeA(1));
helper();
// OK
void fixed_f(tcp::socket &) c=1;
void fixed()
using type1 = tcp::socket;
asio::io_context ioc;
tcp::socket sock(ioc);
auto helper = std::bind(&fixed_f, std::ref(sock));
helper();
// OK
void fail_f(tcp::socket &&) c=1;
void fail()
using type1 = tcp::socket;
asio::io_context ioc;
tcp::socket sock(ioc);
// fail_f(std::move(sock));
// OK
auto helper = std::bind(&fail_f, std::move(sock));
helper();
// a.cc:34:5: error: no matching function for call to object of type 'std::_Bind<void (*(boost::asio::basic_stream_socket<boost::asio::ip::tcp>))(boost::asio::basic_stream_socket<boost::asio::ip::tcp> &&)>'
// helper();
// ^~~~~~
编译日志和错误:
recolic@RECOLICPC ~/tmp> clang++ --version
clang version 6.0.0 (tags/RELEASE_600/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
recolic@RECOLICPC ~/tmp> clang++ -c a.cc
a.cc:39:5: error: no matching function for call to object of type 'std::_Bind<void (*(boost::asio::basic_stream_socket<boost::asio::ip::tcp>))(boost::asio::basic_stream_socket<boost::asio::ip::tcp> &&)>'
helper();
^~~~~~
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.1.0/../../../../include/c++/8.1.0/functional:480:2: note: candidate template ignored: substitution failure [with _Args = <>]: no type named 'type' in 'std::result_of<void
(*&(boost::asio::basic_stream_socket<boost::asio::ip::tcp> &))(boost::asio::basic_stream_socket<boost::asio::ip::tcp> &&)>'
operator()(_Args&&... __args)
^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.1.0/../../../../include/c++/8.1.0/functional:491:2: note: candidate template ignored: substitution failure [with _Args = <>]: no type named 'type' in 'std::result_of<void (*const &(const
boost::asio::basic_stream_socket<boost::asio::ip::tcp> &))(boost::asio::basic_stream_socket<boost::asio::ip::tcp> &&)>'
operator()(_Args&&... __args) const
^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.1.0/../../../../include/c++/8.1.0/functional:509:2: note: candidate template ignored: substitution failure [with _Args = <>]: no type named 'type' in 'std::result_of<void (*volatile &(volatile
boost::asio::basic_stream_socket<boost::asio::ip::tcp> &))(boost::asio::basic_stream_socket<boost::asio::ip::tcp> &&)>'
operator()(_Args&&... __args) volatile
^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/8.1.0/../../../../include/c++/8.1.0/functional:521:2: note: candidate template ignored: substitution failure [with _Args = <>]: no type named 'type' in 'std::result_of<void (*const volatile &(const volatile
boost::asio::basic_stream_socket<boost::asio::ip::tcp> &))(boost::asio::basic_stream_socket<boost::asio::ip::tcp> &&)>'
operator()(_Args&&... __args) const volatile
^
1 error generated.
我不确定是什么导致了这个错误。你能给我一些建议吗?
【问题讨论】:
写auto f = std::bind(something);
@PasserBy 我已经尝试过了,但没有帮助。返回类型正是我在这里写的。
boost::ip::tcp::socket
不是可复制构造/可赋值的,因此 fail_f
需要通过引用而不是值来接受其 arg。另外,请按照@PasserBy 的建议使用auto
。
绑定参数总是作为左值传递。
@RecolicKeghart 请从您的标题中删除“已解决”,然后添加您的解决方案作为答案。 ***不是论坛。
【参考方案1】:
void fail_f_1(tcp::socket);
std::bind(&fail_f_1, tcp::socket(io_context));
此解决方案失败,因为 boost::asio::ip::tcp::socket
不可复制。
void fail_f_2(tcp::socket &&);
std::bind(&fail_f_2, std::move(tcp::socket(io_context)));
此解决方案失败,因为std::bind
将绑定参数作为左值而不是右值传递。 fixed_f
是一个很好的解决方案。
如果您必须将右值引用作为绑定参数传递,this answer 会有所帮助。
【讨论】:
以上是关于将 std::bind 应用于带有参数 <boost::asio::ip::tcp::socket> 的函数时出错?的主要内容,如果未能解决你的问题,请参考以下文章
第11课 std::bind和std::function_std::bind绑定器