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_nowexpires_at