首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C++为类方法实现超时函数模板

C++为类方法实现超时函数模板
EN

Stack Overflow用户
提问于 2020-10-06 08:33:57
回答 1查看 359关注 0票数 1

我想要达到的目标是,如果进程超过超时时间,程序将停止进程并返回超时错误。

我从second most voted answer to this question获得了一个超时函数。我遇到了一个错误,它说std::result_of_t在c++17中不受欢迎,所以我使用建议的替换std::invoke_result_t重新创建了它,并将其实现如下:

代码语言:javascript
运行
复制
template <typename TF, typename TDuration, class... TArgs>
std::invote_result_t<TF&&, TArgs&&...> run_with_timeout(TF&& f, TDuration timeout, TArgs&&... args)
{
    using R = std::invoke_result_t<TF&&, TArgs&&...>;
    std::packaged_task<R(TArgs...)> task(f);
    auto future = task.get_future();
    std::thread thr(std::move(task), std::forward<TArgs>(args)...);
    if (future.wait_for(timeout) != std::future_status::timeout)
    {
       thr.join();
       return future.get(); // this will propagate exception from f() if any
    }
    else
    {
       thr.detach(); // we leave the thread still running
       throw std::runtime_error("Timeout");
    }
}

我想使用它来检查类方法的函数是否超时。所以我尝试用一种类似于:

代码语言:javascript
运行
复制
template <typename TF, typename TDuration, class... TArgs>
std::invote_result_t<TF&&, TArgs&&...> ClassOne::run_with_timeout(TF&& f, TDuration timeout, TArgs&&... args)
{
    using R = std::invoke_result_t<TF&&, TArgs&&...>;
    std::packaged_task<R(TArgs...)> task(f);
    auto future = task.get_future();
    std::thread thr(std::move(task), std::forward<TArgs>(args)...);
    if (future.wait_for(timeout) != std::future_status::timeout)
    {
       thr.join();
       return future.get(); // this will propagate exception from f() if any
    }
    else
    {
       thr.detach(); // we leave the thread still running
       throw std::runtime_error("Timeout");
    }
}

// The function checked for timeout
int ClassOne::func(ClassTwo *param1, std::string name)
{
    // Some code here...

    // For mimicking function process:
    std::this_thread::sleep_for(10s);
    return 0;
}

// Function which calls the timed process with timeout function
int ClassOne::dummy(ClassTwo *param1, std::string name)
{
    int retVal = 0; // zero for no error, non-zero for error
    try
    {
        retVal = run_with_timeout(func, 20s, param1, name);
    }
    catch (runtime_error & e)
    {
        return 1;
    }
}

通过这个,我得到了一个错误:

代码语言:javascript
运行
复制
no instance of function template "ClassOne::run_with_timeout" matches the argument list
    argument types are: (int (ClassTwo *param1, std::string target), std::chrono::seconds, ClassTwo *, std::string)

我认为这个问题类似于this entry,但我不知道如何纠正它。我需要使用超时函数的某些函数具有不同的对象参数,这就是为什么使用函数模板的原因。

提前感谢您的帮助!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-07 07:28:52

顾名思义,std::invoke_result_t是应用std::invoke的结果类型。我在这里强调了适用于你的情况:

调用(f、t1、t2、.、tN)定义如下:

..。

如果f是一个指向T类成员函数的指针:

如果

  • ,std::decay_t>::value为真,则调用(f,t1,t2,.,tN)等价于(t1.*f)(t2,.,tN)
  • ,如果t1不满足前面的项,则调用(f,t1,t2,.,tN)等效于(*t1).*f(
  • ,.,)。

所以你的电话应该是:

代码语言:javascript
运行
复制
retVal = run_with_timeout(&ClassOne::func, 20s, this, std::move(param1), std::move(name));

编辑:为了让它真正发挥作用,我挣扎了二十分钟。添加上面的std::move或通过const引用获取name (在dummy中)使其编译。对于param1,我想不出类似的转换。我很想知道这个错误背后的原因,但至少你眼前的问题已经解决了。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64222123

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档