解决no type named ‘completion_handler_type’ in ‘class boost::asio::async_result’错误

尝试为boost.asio封装一个有栈协程异步方法,一直报标题这个错误。给官方提交了bug:no type named ‘completion_handler_type’ in ‘class boost::asio::async_result’ · Issue #1255 · chriskohlhoff/asio · GitHub

好多天没有人回复,昨晚上在stackoverflow上提交了问题,早上查看就有人帮解决了。

先看最初的代码,之前网上能搜到的代码都是类似这种形式,在Boost1.81上编译会报错:

// TestAsync.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
 
#include <iostream>
#include <boost/asio/spawn.hpp>
#include <boost/asio.hpp>
#include <boost/thread/future.hpp>
 
 
template<typename CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(boost::system::error_code, int))
async_do_something(BOOST_ASIO_MOVE_ARG(CompletionToken) token)
{
    boost::asio::async_completion<CompletionToken, void(boost::system::error_code, int)> completion(token);
 
    boost::async(boost::launch::async, [handler = completion.completion_handler]() mutable
    {
        boost::system::error_code ec;
        int result = 0;
 
        // 执行操作,并拿到result或ec...
        std::this_thread::sleep_for(std::chrono::seconds(5));
        result = 100;
 
        auto executor = boost::asio::get_associated_executor(handler);
        boost::asio::dispatch(executor, [ec, handler, result]() mutable
        {
            handler(ec, result);
        });
    });
 
    return completion.result.get();
}
 
void MyCoroutine(boost::asio::yield_context yield) {
    std::cout << "进入MyCoroutine" << std::endl;
    boost::system::error_code ec;
    int n = async_do_something(yield[ec]);
    if (ec)
        std::cerr << ec.message() << std::endl;
    else
        std::cout << n << std::endl;
    std::cout << "离开MyCoroutine" << std::endl;
}
 
int main()
{
    boost::asio::io_context ioc;
 
    boost::asio::spawn(ioc, MyCoroutine);
    ioc.run();
}

 GCC9.2编译错误信息:

In file included from ../boost_1_81_0/boost/asio/detail/handler_type_requirements.hpp:53,
                 from ../boost_1_81_0/boost/asio/impl/execution_context.hpp:18,
                 from ../boost_1_81_0/boost/asio/execution_context.hpp:409,
                 from ../boost_1_81_0/boost/asio/any_io_executor.hpp:23,
                 from ../boost_1_81_0/boost/asio/spawn.hpp:19,
                 from main.cpp:5:
../boost_1_81_0/boost/asio/async_result.hpp: In instantiation of ‘struct boost::asio::async_completion<boost::asio::basic_yield_context<boost::asio::any_io_executor>, void(boost::system::error_code, int)>’:
main.cpp:14:87:   required from ‘typename boost::asio::async_result<typename std::decay<_Tp>::type, void(boost::system::error_code, int)>::return_type async_do_something(CompletionToken&&) [with CompletionToken = boost::asio::basic_yield_context<boost::asio::any_io_executor>; typename boost::asio::async_result<typename std::decay<_Tp>::type, void(boost::system::error_code, int)>::return_type = int]’
main.cpp:38:38:   required from here
../boost_1_81_0/boost/asio/async_result.hpp:651:9: error: no type named ‘completion_handler_type’ in ‘class boost::asio::async_result<boost::asio::basic_yield_context<boost::asio::any_io_executor>, void(boost::system::error_code, int)>’
  651 |         completion_handler_type;
      |         ^~~~~~~~~~~~~~~~~~~~~~~
../boost_1_81_0/boost/asio/async_result.hpp:684:62: error: no type named ‘completion_handler_type’ in ‘class boost::asio::async_result<boost::asio::basic_yield_context<boost::asio::any_io_executor>, void(boost::system::error_code, int)> ’
  684 |     completion_handler_type&, completion_handler_type>::type completion_handler;
      |                                                              ^~~~~~~~~~~~~~~~~~
main.cpp: In instantiation of ‘typename boost::asio::async_result<typename std::decay<_Tp>::type, void(boost::system::error_code, int)>::return_type async_do_something(CompletionToken&&) [with CompletionToken = boost::asio::basic_yield_context<boost::asio::any_io_executor>; typename boost::asio::async_result<typename std::decay<_Tp>::type, void(boost::system::error_code, int)>::return_type = int]’:
main.cpp:38:38:   required from here
main.cpp:16:59: error: ‘struct boost::asio::async_completion<boost::asio::basic_yield_context<boost::asio::any_io_executor>, void(boost::system::error_code, int)>’ has no member named ‘completion_handler’; did you mean ‘completion_handler_type’?
   16 |  boost::async(boost::launch::async, [handler = completion.completion_handler]() mutable
      |                                                ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
      |                                                completion_handler_type
main.cpp:32:27: error: ‘class boost::asio::async_result<boost::asio::basic_yield_context<boost::asio::any_io_executor>, void(boost::system::error_code, int)>’ has no member named ‘get’
   32 |  return completion.result.get();

VS2022编译错误信息:

严重性 代码 说明 项目 文件 行 禁止显示状态
错误 C2039 "completion_handler_type": 不是 "boost::asio::async_result<boost::asio::basic_yield_contextboost::asio::any_io_executor,void (boost::system::error_code,int)>" 的成员 TestAsync D:\library\boost_1_81_0\boost\asio\async_result.hpp 650
错误 C3646 “completion_handler_type”: 未知重写说明符 TestAsync D:\library\boost_1_81_0\boost\asio\async_result.hpp 651
错误 C4430 缺少类型说明符 - 假定为 int。注意: C++ 不支持默认 int TestAsync D:\library\boost_1_81_0\boost\asio\async_result.hpp 651
错误 C2064 项不会计算为接受 2 个参数的函数 TestAsync C:\Users\laf163\Desktop\TestAsync\TestAsync\TestAsync.cpp 23
错误 C2039 "get": 不是 "boost::asio::async_result<boost::asio::basic_yield_contextboost::asio::any_io_executor,void (boost::system::error_code,int)>" 的成员 TestAsync C:\Users\laf163\Desktop\TestAsync\TestAsync\TestAsync.cpp 27

老外提供的修改后的代码:

#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/thread/future.hpp>
#include <iostream>
#include <thread>

namespace asio = boost::asio;

template <typename Token>
typename asio::async_result<typename std::decay<Token>::type,
    void(boost::system::error_code, int)>::return_type
    async_do_something(Token&& token) {
    auto init = [](auto handler) {
        boost::async(
            boost::launch::async,
            [handler = std::move(handler), work = make_work_guard(handler)]() mutable {
            boost::system::error_code ec;
            int result = 0;

            std::this_thread::sleep_for(std::chrono::seconds(5));
            result = 100;

            auto executor = asio::get_associated_executor(handler);
            asio::dispatch(executor, [ec, handler = std::move(handler), result]() mutable {
                std::move(handler)(ec, result);
            });
        });
    };

    return asio::async_initiate<Token, void(boost::system::error_code, int)>(init, token);
}

void MyCoroutine(asio::yield_context yield) {
    std::cout << "Enter MyCoroutine" << std::endl;

    boost::system::error_code ec;
    int n = async_do_something(yield[ec]);
    if (ec)
        std::cerr << ec.message() << std::endl;
    else
        std::cout << n << std::endl;
    std::cout << "Leave MyCoroutine" << std::endl;
}

int main() {
    asio::io_context ioc;
    asio::spawn(ioc, MyCoroutine);
    ioc.run();
}

详细信息参考:no type named ‘completion_handler_type’ in ‘class boost::asio::async_result’ - Stack Overflow

模型声明和签名可以简化为:

template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(boost::system::error_code, int)) Token>
auto async_do_something(Token&& token) {
    // ......
}

参考官方文档:

Completion Tokens - 1.83.0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值