C++ 通用指数退避重试机制C++;11

C++ 通用指数退避重试机制C++;11,c++,c++11,C++,C++11,我在C++11中编写了一个通用的指数回退重试循环。我正在使用std::function传递可调用重试循环callable #include <algorithm> #include <cassert> #include <chrono> #include <functional> #include <iostream> #include <thread> constexpr int64_t max_backoff_mill

我在C++11中编写了一个通用的指数回退重试循环。我正在使用
std::function
传递可调用重试循环<如果
isRetrable
函数返回true,则将重试code>callable

#include <algorithm>
#include <cassert>
#include <chrono>
#include <functional>
#include <iostream>
#include <thread>

constexpr int64_t max_backoff_milliseconds = 30000; // 30 seconds

template <class R, class... Args>
R Retry(int max_retry_count, int64_t initial_dealy_milliseconds,
    const std::function<bool(R)> &isRetriable,
    const std::function<R(Args...)> &callable, Args &&... args)
{
    int retry_count = 0;
    while (true) {
        auto status = callable(std::forward<Args>(args)...);
        if (!IsRetriable(status)) {
            return status;
        }

       if (retry_count >= max_retry_count) {
           // Return status and abort retry
           return status;
       }
       int64_t delay_milliseconds = 0;
       if (initial_dealy_milliseconds > 0) {
           delay_milliseconds =
               std::min(initial_dealy_milliseconds << retry_count,
                     max_backoff_milliseconds);
       }
       std::cout << "Callable execution failed. Retry Count:"
              << retry_count + 1 << std::endl;
       std::this_thread::sleep_for(
           std::chrono::milliseconds(delay_milliseconds));
      retry_count++;
   }
}

bool isRetriable(int status) {
    if (status == 5)
       return true;
    return false;
}

int foo(int x, int y) {
    static int a = 1;
    a += (x + y);
    return a / 6;
}

int main() {
    auto result = Retry(1000, 100, isRetriable, foo, 1, 3);
    std::cout << result << std::endl;
    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
constexpr int64\u t max\u backoff\u毫秒=30000;//30秒
模板
R重试(整数最大重试计数,整数初始延迟毫秒,
常量标准::函数和可测量,
常量std::函数和可调用参数(Args&&…Args)
{
int重试次数=0;
while(true){
自动状态=可调用(std::forward(args)…);
如果(!isRetrable(状态)){
返回状态;
}
如果(重试次数>=最大重试次数){
//返回状态并中止重试
返回状态;
}
int64_t延迟_毫秒=0;
如果(初始时间>0毫秒){
延迟(毫秒)=

std::min(初始时间-毫秒我确信这有一个很好的副本,但是

这是一个简短的复制:

template <typename T> void foo(std::function<bool(T)> ) { }
bool maybe(int ) { return false; }

foo(maybe); // error: no matching function call to 'foo(bool (&)(int))'
基本上,试图推断一个
std::function
几乎总是错误的。首先,它是错误的,因为它不起作用。其次,它是错误的,因为即使它起作用,你也会在你可能不需要它的上下文中发生类型擦除

相反,您要做的是推断任意可调用项,然后确定这些其他参数基于这些可调用项。当您使用
Args…
调用
callable
时,
callable
的返回类型就是您得到的,并且您要确保
isRetriable
是该类型的谓词

一种方法是:

template <typename Predicate, typename Callable, typename... Args,
    // figure out what the callable returns
    typename R = std::decay_t<std::invoke_result_t<Callable&, Args...>>,
    // require that Predicate is actually a Predicate
    std::enable_if_t<
        std::is_convertible_v<std::invoke_result_t<Predicate&, R>, bool>,
        int> = 0>
R Retry(int max_retry_count, int64_t initial_dealy_milliseconds,
    Predicate&& isRetriable,
    Callable&& callable,
    Args&&... args)
{
    // ....
}
template=0>
R重试(整数最大重试计数,整数初始延迟毫秒,
谓词可度量(&I),
可调用&&Callable,
Args&&…Args)
{
// ....
}

您正在(尝试)调用一个签名与现有签名不同的函数。在C++14中,删除所有的enable_if和invoke_result内容,只需返回
auto
,即可完成90%的功能,完成10%的工作。@Yakk AdamNevraumont-您能为问题中所示的重试机制提供C++14解决方案吗?想知道函数的签名吗以及如何称呼它。
foo([](int ) { return true; }); // also error
template <typename Predicate, typename Callable, typename... Args,
    // figure out what the callable returns
    typename R = std::decay_t<std::invoke_result_t<Callable&, Args...>>,
    // require that Predicate is actually a Predicate
    std::enable_if_t<
        std::is_convertible_v<std::invoke_result_t<Predicate&, R>, bool>,
        int> = 0>
R Retry(int max_retry_count, int64_t initial_dealy_milliseconds,
    Predicate&& isRetriable,
    Callable&& callable,
    Args&&... args)
{
    // ....
}