You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确初始化std::stop_callback?相关C++回调注册问题

问题解答

1. 修正watch_dog类中std::stop_callback的初始化方式

原代码核心问题是**std::stop_callback是模板类,声明时必须指定回调类型**,且初始化需保证参数传递合规。以下是两种可行修正方案:

方案一:使用Lambda表达式(推荐)

Lambda可通过std::function<void()>适配,代码简洁直观:

#include <stop_token>
#include <functional>
#include <iostream>

class watch_dog
{
public:
    watch_dog(std::stop_token token) :
        m_token(std::move(token)),
        m_callback(m_token, [this](){ callback_proc(); })
    {
    }

private:
    void callback_proc()
    {
        std::cout << "an operation has completed." << std::endl;
    }

    std::stop_token m_token;
    std::stop_callback<std::function<void()>> m_callback;
};

方案二:保留std::bind,用decltype推导类型

通过decltype获取std::bind返回类型,提前定义类型别名:

#include <stop_token>
#include <functional>
#include <iostream>

class watch_dog;
// 提前推导bind的类型
using BindCallbackType = decltype(std::bind(&watch_dog::callback_proc, static_cast<watch_dog*>(nullptr)));

class watch_dog
{
public:
    watch_dog(std::stop_token token) :
        m_token(std::move(token)),
        m_callback(m_token, std::bind(&watch_dog::callback_proc, this))
    {
    }

private:
    void callback_proc()
    {
        std::cout << "an operation has completed." << std::endl;
    }

    std::stop_token m_token;
    std::stop_callback<BindCallbackType> m_callback;
};

注意:用std::move传递stop_token可避免不必要拷贝,提升效率。

2. 不使用std::stop_callback注册回调的方法

存在多种替代方式,核心是手动监听std::stop_token的停止请求:

  • 轮询检查:在循环中调用stop_token::stop_requested(),返回true时执行回调逻辑。
  • 配合条件变量:使用stop_token::wait()方法,该方法会在停止请求到来时返回,随后触发回调。示例:
    void listen_stop(std::stop_token token) {
        std::condition_variable_any cv;
        std::mutex mtx;
        std::unique_lock lock(mtx);
        // 等待停止请求
        token.wait(cv, []{ return false; });
        // 执行回调
        std::cout << "Stop requested!" << std::endl;
    }
    
  • 自定义回调机制:维护回调函数列表,在独立线程中监听stop_token,检测到停止请求时遍历执行所有回调。

3. 确定std::bind的类型以声明std::stop_callback

通过decltype推导std::bind的返回类型,步骤如下:

  1. 提前声明类,用static_cast<watch_dog*>(nullptr)模拟this指针类型(类内部声明时无法直接使用this)。
  2. 定义类型别名存储推导结果:
    class watch_dog;
    using BindType = decltype(std::bind(&watch_dog::callback_proc, static_cast<watch_dog*>(nullptr)));
    
  3. 使用该别名声明std::stop_callback成员:
    std::stop_callback<BindType> m_callback;
    

也可在构造函数中直接用decltype(std::bind(...))作为模板参数,但提前定义类型别名能保证类型在成员声明时可见,更稳妥。


内容的提问来源于stack exchange,提问作者Alexey Starinsky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 07:43:19