boost::deadline_timer error: static assertion failed: WaitHandler type requirements not met
boost::deadline_timer error: static assertion failed: WaitHandler type requirements not met
我有一个 cnx
class 代表一个套接字,它还必须有一个计时器,如果客户端停留超过 cnx::timeout_mili
毫秒没有响应,那么我将关闭连接。每个计时器将在建立连接时启动,或者在实例化 cnx
对象时启动。套接字部分工作正常,现在当我尝试将计时器添加到 cnx
class 时,它的构建失败并出现以下错误:
In file included from /home/pcuser/src/boost_1_71_0/boost/asio/impl/execution_context.hpp:18,
from /home/pcuser/src/boost_1_71_0/boost/asio/execution_context.hpp:409,
from /home/pcuser/src/boost_1_71_0/boost/asio/detail/scheduler.hpp:21,
from /home/pcuser/src/boost_1_71_0/boost/asio/system_context.hpp:19,
from /home/pcuser/src/boost_1_71_0/boost/asio/impl/system_executor.hpp:22,
from /home/pcuser/src/boost_1_71_0/boost/asio/system_executor.hpp:129,
from /home/pcuser/src/boost_1_71_0/boost/asio/associated_executor.hpp:21,
from /home/pcuser/src/boost_1_71_0/boost/asio.hpp:21,
from /home/pcuser/src/cpp-server/comum.h:9,
from /home/pcuser/src/cpp-server/cnx.h:4,
from /home/pcuser/src/cpp-server/cnx.cpp:1:
/home/pcuser/src/boost_1_71_0/boost/asio/basic_deadline_timer.hpp: In instantiation of ‘void boost::asio::basic_deadline_timer<Time, TimeTraits, Executor>::initiate_async_wait::operator()(WaitHandler&&, boost::asio::basic_deadline_timer<Time, TimeTraits, Executor>*) const [with WaitHandler = void (cnx::*)(const boost::system::error_code&); Time = boost::posix_time::ptime; TimeTraits = boost::asio::time_traits<boost::posix_time::ptime>; Executor = boost::asio::executor]’:
/home/pcuser/src/boost_1_71_0/boost/asio/async_result.hpp:82:49: required from ‘static boost::asio::async_result<CompletionToken, Signature>::return_type boost::asio::async_result<CompletionToken, Signature>::initiate(Initiation&&, RawCompletionToken&&, Args&& ...) [with Initiation = boost::asio::basic_deadline_timer<boost::posix_time::ptime>::initiate_async_wait; RawCompletionToken = void (cnx::*)(const boost::system::error_code&); Args = {boost::asio::basic_deadline_timer<boost::posix_time::ptime, boost::asio::time_traits<boost::posix_time::ptime>, boost::asio::executor>*}; CompletionToken = void (cnx::*)(const boost::system::error_code&); Signature = void(boost::system::error_code); boost::asio::async_result<CompletionToken, Signature>::return_type = void]’
/home/pcuser/src/boost_1_71_0/boost/asio/async_result.hpp:257:25: required from ‘typename std::enable_if<boost::asio::detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value, typename boost::asio::async_result<typename std::decay<_Tp>::type, Signature>::return_type>::type boost::asio::async_initiate(Initiation&&, CompletionToken&, Args&& ...) [with CompletionToken = void (cnx::*)(const boost::system::error_code&); Signature = void(boost::system::error_code); Initiation = boost::asio::basic_deadline_timer<boost::posix_time::ptime>::initiate_async_wait; Args = {boost::asio::basic_deadline_timer<boost::posix_time::ptime, boost::asio::time_traits<boost::posix_time::ptime>, boost::asio::executor>*}; typename std::enable_if<boost::asio::detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value, typename boost::asio::async_result<typename std::decay<_Tp>::type, Signature>::return_type>::type = void; typename boost::asio::async_result<typename std::decay<_Tp>::type, Signature>::return_type = void; typename std::decay<_Tp>::type = void (cnx::*)(const boost::system::error_code&)]’
/home/pcuser/src/boost_1_71_0/boost/asio/basic_deadline_timer.hpp:629:73: required from ‘typename boost::asio::async_result<typename std::decay<_Functor>::type, void(boost::system::error_code)>::return_type boost::asio::basic_deadline_timer<Time, TimeTraits, Executor>::async_wait(WaitHandler&&) [with WaitHandler = void (cnx::*)(const boost::system::error_code&); Time = boost::posix_time::ptime; TimeTraits = boost::asio::time_traits<boost::posix_time::ptime>; Executor = boost::asio::executor; typename boost::asio::async_result<typename std::decay<_Functor>::type, void(boost::system::error_code)>::return_type = void; typename std::decay<_Functor>::type = void (cnx::*)(const boost::system::error_code&)]’
/home/pcuser/src/cpp-server/cnx.cpp:15:25: required from here
/home/pcuser/src/boost_1_71_0/boost/asio/detail/handler_type_requirements.hpp:376:62: error: static assertion failed: WaitHandler type requirements not met
373 | sizeof(boost::asio::detail::one_arg_handler_test( \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
374 | boost::asio::detail::rvref< \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
375 | asio_true_handler_type>(), \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
376 | static_cast<const boost::system::error_code*>(0))) == 1, \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
/home/pcuser/src/boost_1_71_0/boost/asio/detail/handler_type_requirements.hpp:105:20: note: in definition of macro ‘BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT’
105 | static_assert(expr, msg);
| ^~~~
/home/pcuser/src/boost_1_71_0/boost/asio/basic_deadline_timer.hpp:647:7: note: in expansion of macro ‘BOOST_ASIO_WAIT_HANDLER_CHECK’
647 | BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/pcuser/src/boost_1_71_0/boost/asio/detail/handler_type_requirements.hpp:376:62: note: ‘(sizeof (boost::asio::detail::one_arg_handler_test<void (cnx::*)(const boost::system::error_code&)>(boost::asio::detail::rvref<void (cnx::*)(const boost::system::error_code&)>(), 0)) == 1)’ evaluates to false
373 | sizeof(boost::asio::detail::one_arg_handler_test( \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
374 | boost::asio::detail::rvref< \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
375 | asio_true_handler_type>(), \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
376 | static_cast<const boost::system::error_code*>(0))) == 1, \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
/home/pcuser/src/boost_1_71_0/boost/asio/detail/handler_type_requirements.hpp:105:20: note: in definition of macro ‘BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT’
105 | static_assert(expr, msg);
| ^~~~
/home/pcuser/src/boost_1_71_0/boost/asio/basic_deadline_timer.hpp:647:7: note: in expansion of macro ‘BOOST_ASIO_WAIT_HANDLER_CHECK’
647 | BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/pcuser/src/boost_1_71_0/boost/asio/detail/handler_type_requirements.hpp:280:36: error: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘boost::asio::detail::lvref<void (cnx::*)(const boost::system::error_code&)>() (...)’, e.g. ‘(... ->* boost::asio::detail::lvref<void (cnx::*)(const boost::system::error_code&)>()) (...)’
279 | boost::asio::detail::lvref< \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
280 | asio_true_handler_type>()( \
| ~~~~~~~~~~~~~~~~~~~~~~~~~^~~
281 | boost::asio::detail::lvref<const boost::system::error_code>()), \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/pcuser/src/boost_1_71_0/boost/asio/basic_socket.hpp:1817:7: note: in expansion of macro ‘BOOST_ASIO_CONNECT_HANDLER_CHECK’
1817 | BOOST_ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
make[2]: *** [CMakeFiles/Server.dir/build.make:90: CMakeFiles/Server.dir/cnx.cpp.o] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/Server.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
我的代码如下:
cnx.h
#ifndef CNX_H
#define CNX_H
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
typedef boost::asio::io_service ioservice;
using namespace std;
class cnx
{
public:
inline static int timeout_mili = 10000;
cnx(ioservice& io);
void timer_counter_reset();
bool conectado;
private:
tcp::socket s;
boost::asio::io_service timer_io;
boost::asio::deadline_timer cnx_timer;
void timer_ended(const boost::system::error_code& e);
};
#endif // CNX_H
cnx.cpp
#include "cnx.h"
cnx::cnx(ioservice& io) :
s(tcp::socket(io)),
conectado(false),
cnx_timer(boost::asio::deadline_timer(timer_io, boost::posix_time::milliseconds(cnx::timeout_mili)))
{
timer_io.run();
cnx_timer.async_wait(&cnx::timer_ended);
}
// I'll call this outsite so the timer gets reset and restart couting
void cnx::timer_counter_reset()
{
cnx_timer.cancel();
cnx_timer.async_wait(&cnx::timer_ended);
}
void cnx::timer_ended(const boost::system::error_code& e)
{
if(e){
cout << "cnx id " << id << " resetted timer" << endl;
return;
}
this->conectado = false;
}
我不知道我在函数签名上做错了什么。另外我的问题似乎还没有得到回答 。提前致谢。
编辑
所以,问题似乎是在 async_wait
调用中引用方法 &cnx::timer_ended
时,我在 cnx.h 中添加了一个测试函数,如下所示:
inline static void testtt(const boost::system::error_code& e)
{
cout << "testtt" << endl;
return;
}
并更改了 async_await 调用
cnx_timer.async_wait(&cnx::timer_ended);
到 cnx_timer.async_wait(cnx::testtt);
它奏效了。但是我仍然不知道如何解决它,因为我需要为 cnx
个对象的每个实例更改一个值,所以我不能使用静态函数...有什么想法吗?
编辑 2
即使现在正在编译,代码也没有按预期工作,函数“testtt”根本没有被触发。
这是绑定成员函数的经典“问题”。对于成员函数,您还需要有一个“this
值”,它从哪里来?
大致有两种做法:
- 绑定
- λ
绑定
使用例如boost::bind
你可以
cnx_timer.async_wait(boost::bind(&cnx::timer_ended, this,
boost::asio::placeholders::error()));
现在回调绑定到this
。请记住,您必须确保 cnx
对象保持有效。还要记住线程安全。
旁注;
// I'll call this outsite so the timer gets reset and restart couting
void cnx::timer_counter_reset()
{
cnx_timer.cancel();
这不会重置计时器。它只是取消任何挂起的异步等待。要实际重置它,请再次使用 expires_from_now
或 expires_at
。
我有一个 cnx
class 代表一个套接字,它还必须有一个计时器,如果客户端停留超过 cnx::timeout_mili
毫秒没有响应,那么我将关闭连接。每个计时器将在建立连接时启动,或者在实例化 cnx
对象时启动。套接字部分工作正常,现在当我尝试将计时器添加到 cnx
class 时,它的构建失败并出现以下错误:
In file included from /home/pcuser/src/boost_1_71_0/boost/asio/impl/execution_context.hpp:18,
from /home/pcuser/src/boost_1_71_0/boost/asio/execution_context.hpp:409,
from /home/pcuser/src/boost_1_71_0/boost/asio/detail/scheduler.hpp:21,
from /home/pcuser/src/boost_1_71_0/boost/asio/system_context.hpp:19,
from /home/pcuser/src/boost_1_71_0/boost/asio/impl/system_executor.hpp:22,
from /home/pcuser/src/boost_1_71_0/boost/asio/system_executor.hpp:129,
from /home/pcuser/src/boost_1_71_0/boost/asio/associated_executor.hpp:21,
from /home/pcuser/src/boost_1_71_0/boost/asio.hpp:21,
from /home/pcuser/src/cpp-server/comum.h:9,
from /home/pcuser/src/cpp-server/cnx.h:4,
from /home/pcuser/src/cpp-server/cnx.cpp:1:
/home/pcuser/src/boost_1_71_0/boost/asio/basic_deadline_timer.hpp: In instantiation of ‘void boost::asio::basic_deadline_timer<Time, TimeTraits, Executor>::initiate_async_wait::operator()(WaitHandler&&, boost::asio::basic_deadline_timer<Time, TimeTraits, Executor>*) const [with WaitHandler = void (cnx::*)(const boost::system::error_code&); Time = boost::posix_time::ptime; TimeTraits = boost::asio::time_traits<boost::posix_time::ptime>; Executor = boost::asio::executor]’:
/home/pcuser/src/boost_1_71_0/boost/asio/async_result.hpp:82:49: required from ‘static boost::asio::async_result<CompletionToken, Signature>::return_type boost::asio::async_result<CompletionToken, Signature>::initiate(Initiation&&, RawCompletionToken&&, Args&& ...) [with Initiation = boost::asio::basic_deadline_timer<boost::posix_time::ptime>::initiate_async_wait; RawCompletionToken = void (cnx::*)(const boost::system::error_code&); Args = {boost::asio::basic_deadline_timer<boost::posix_time::ptime, boost::asio::time_traits<boost::posix_time::ptime>, boost::asio::executor>*}; CompletionToken = void (cnx::*)(const boost::system::error_code&); Signature = void(boost::system::error_code); boost::asio::async_result<CompletionToken, Signature>::return_type = void]’
/home/pcuser/src/boost_1_71_0/boost/asio/async_result.hpp:257:25: required from ‘typename std::enable_if<boost::asio::detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value, typename boost::asio::async_result<typename std::decay<_Tp>::type, Signature>::return_type>::type boost::asio::async_initiate(Initiation&&, CompletionToken&, Args&& ...) [with CompletionToken = void (cnx::*)(const boost::system::error_code&); Signature = void(boost::system::error_code); Initiation = boost::asio::basic_deadline_timer<boost::posix_time::ptime>::initiate_async_wait; Args = {boost::asio::basic_deadline_timer<boost::posix_time::ptime, boost::asio::time_traits<boost::posix_time::ptime>, boost::asio::executor>*}; typename std::enable_if<boost::asio::detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value, typename boost::asio::async_result<typename std::decay<_Tp>::type, Signature>::return_type>::type = void; typename boost::asio::async_result<typename std::decay<_Tp>::type, Signature>::return_type = void; typename std::decay<_Tp>::type = void (cnx::*)(const boost::system::error_code&)]’
/home/pcuser/src/boost_1_71_0/boost/asio/basic_deadline_timer.hpp:629:73: required from ‘typename boost::asio::async_result<typename std::decay<_Functor>::type, void(boost::system::error_code)>::return_type boost::asio::basic_deadline_timer<Time, TimeTraits, Executor>::async_wait(WaitHandler&&) [with WaitHandler = void (cnx::*)(const boost::system::error_code&); Time = boost::posix_time::ptime; TimeTraits = boost::asio::time_traits<boost::posix_time::ptime>; Executor = boost::asio::executor; typename boost::asio::async_result<typename std::decay<_Functor>::type, void(boost::system::error_code)>::return_type = void; typename std::decay<_Functor>::type = void (cnx::*)(const boost::system::error_code&)]’
/home/pcuser/src/cpp-server/cnx.cpp:15:25: required from here
/home/pcuser/src/boost_1_71_0/boost/asio/detail/handler_type_requirements.hpp:376:62: error: static assertion failed: WaitHandler type requirements not met
373 | sizeof(boost::asio::detail::one_arg_handler_test( \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
374 | boost::asio::detail::rvref< \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
375 | asio_true_handler_type>(), \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
376 | static_cast<const boost::system::error_code*>(0))) == 1, \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
/home/pcuser/src/boost_1_71_0/boost/asio/detail/handler_type_requirements.hpp:105:20: note: in definition of macro ‘BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT’
105 | static_assert(expr, msg);
| ^~~~
/home/pcuser/src/boost_1_71_0/boost/asio/basic_deadline_timer.hpp:647:7: note: in expansion of macro ‘BOOST_ASIO_WAIT_HANDLER_CHECK’
647 | BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/pcuser/src/boost_1_71_0/boost/asio/detail/handler_type_requirements.hpp:376:62: note: ‘(sizeof (boost::asio::detail::one_arg_handler_test<void (cnx::*)(const boost::system::error_code&)>(boost::asio::detail::rvref<void (cnx::*)(const boost::system::error_code&)>(), 0)) == 1)’ evaluates to false
373 | sizeof(boost::asio::detail::one_arg_handler_test( \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
374 | boost::asio::detail::rvref< \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
375 | asio_true_handler_type>(), \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
376 | static_cast<const boost::system::error_code*>(0))) == 1, \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
/home/pcuser/src/boost_1_71_0/boost/asio/detail/handler_type_requirements.hpp:105:20: note: in definition of macro ‘BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT’
105 | static_assert(expr, msg);
| ^~~~
/home/pcuser/src/boost_1_71_0/boost/asio/basic_deadline_timer.hpp:647:7: note: in expansion of macro ‘BOOST_ASIO_WAIT_HANDLER_CHECK’
647 | BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/pcuser/src/boost_1_71_0/boost/asio/detail/handler_type_requirements.hpp:280:36: error: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘boost::asio::detail::lvref<void (cnx::*)(const boost::system::error_code&)>() (...)’, e.g. ‘(... ->* boost::asio::detail::lvref<void (cnx::*)(const boost::system::error_code&)>()) (...)’
279 | boost::asio::detail::lvref< \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
280 | asio_true_handler_type>()( \
| ~~~~~~~~~~~~~~~~~~~~~~~~~^~~
281 | boost::asio::detail::lvref<const boost::system::error_code>()), \
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/pcuser/src/boost_1_71_0/boost/asio/basic_socket.hpp:1817:7: note: in expansion of macro ‘BOOST_ASIO_CONNECT_HANDLER_CHECK’
1817 | BOOST_ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
make[2]: *** [CMakeFiles/Server.dir/build.make:90: CMakeFiles/Server.dir/cnx.cpp.o] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/Server.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
我的代码如下:
cnx.h
#ifndef CNX_H
#define CNX_H
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
typedef boost::asio::io_service ioservice;
using namespace std;
class cnx
{
public:
inline static int timeout_mili = 10000;
cnx(ioservice& io);
void timer_counter_reset();
bool conectado;
private:
tcp::socket s;
boost::asio::io_service timer_io;
boost::asio::deadline_timer cnx_timer;
void timer_ended(const boost::system::error_code& e);
};
#endif // CNX_H
cnx.cpp
#include "cnx.h"
cnx::cnx(ioservice& io) :
s(tcp::socket(io)),
conectado(false),
cnx_timer(boost::asio::deadline_timer(timer_io, boost::posix_time::milliseconds(cnx::timeout_mili)))
{
timer_io.run();
cnx_timer.async_wait(&cnx::timer_ended);
}
// I'll call this outsite so the timer gets reset and restart couting
void cnx::timer_counter_reset()
{
cnx_timer.cancel();
cnx_timer.async_wait(&cnx::timer_ended);
}
void cnx::timer_ended(const boost::system::error_code& e)
{
if(e){
cout << "cnx id " << id << " resetted timer" << endl;
return;
}
this->conectado = false;
}
我不知道我在函数签名上做错了什么。另外我的问题似乎还没有得到回答
编辑
所以,问题似乎是在 async_wait
调用中引用方法 &cnx::timer_ended
时,我在 cnx.h 中添加了一个测试函数,如下所示:
inline static void testtt(const boost::system::error_code& e)
{
cout << "testtt" << endl;
return;
}
并更改了 async_await 调用
cnx_timer.async_wait(&cnx::timer_ended);
到 cnx_timer.async_wait(cnx::testtt);
它奏效了。但是我仍然不知道如何解决它,因为我需要为 cnx
个对象的每个实例更改一个值,所以我不能使用静态函数...有什么想法吗?
编辑 2 即使现在正在编译,代码也没有按预期工作,函数“testtt”根本没有被触发。
这是绑定成员函数的经典“问题”。对于成员函数,您还需要有一个“this
值”,它从哪里来?
大致有两种做法:
- 绑定
- λ
绑定
使用例如boost::bind
你可以
cnx_timer.async_wait(boost::bind(&cnx::timer_ended, this,
boost::asio::placeholders::error()));
现在回调绑定到this
。请记住,您必须确保 cnx
对象保持有效。还要记住线程安全。
旁注;
// I'll call this outsite so the timer gets reset and restart couting
void cnx::timer_counter_reset()
{
cnx_timer.cancel();
这不会重置计时器。它只是取消任何挂起的异步等待。要实际重置它,请再次使用 expires_from_now
或 expires_at
。