包装器到std :: async()不起作用

Wrapper to std::async() not working

本文关键字:不起作用 async 包装 std      更新时间:2023-10-16

编辑:可以用其他东西替换对std :: bind()的调用,我只希望runAsyncternInexoception()与std :: async()一样使用相同的签名,就像只是一个包装器

我正在尝试为std :: async()创建包装器。当直接致电std :: async()起作用时,您知道如何使包装器也可以工作吗?

注意:我不会修改print()函数签名,这是一个示例。我希望包装器是通用的,并为通过直接调用std :: async()的直接调用来处理所有可能的参数。

谢谢。

http://ideone.com/hbbqeo

#include <iostream>
#include <functional>
#include <future>
template<class Fn, class... Args>
inline auto runAsyncTerminateOnException(Fn&& fn, Args&&... args) {
    auto make_call = std::bind(std::forward<Fn>(fn), std::forward<Args>(args)...);
    return std::async(std::launch::async, [=]() -> decltype(make_call()) {
        try {
            return make_call();
        } catch (...) {
            std::cout << "Terminate Called!" << std::endl;
            std::terminate();
        }
    });
}
struct Foo {
    template<class... Args>
    void print(Args&&... args) {
        printf("Foo::print(%d)n", std::forward<Args>(args)...);
    }
};
int main() {
    Foo foo;
    std::future<void> future = std::async(std::launch::async, &Foo::print<int>, &foo, 2);
    std::future<void> future2 = runAsyncTerminateOnException(&Foo::print<int>, &foo, 2);
    // your code goes here
    return 0;
}

您需要更改runAsyncTerminateOnException调用如下:

std::future<void> future2 = 
    runAsyncTerminateOnException(&Foo::print<const int&>, &foo, 2);

这是由于std::bind,variadic模板和完美转发之间的不幸相互作用。

我建议您改用lambdas,几乎总是优于 std::bind(有关更多信息,请参阅STL的此演讲。)

template<class Fn>
inline auto runAsyncTerminateOnException(Fn&& fn) 
{    
    return std::async(std::launch::async, [=]() -> decltype(fn()) {
        try {
            return fn();
        } catch (...) {
            std::cout << "Terminate Called!" << std::endl;
            std::terminate();
        }
    });
}

(请注意,我正在将fn复制到lambda中 - 如果您想要更正确和通用的解决方案,则应考虑将对象捕获到lambda中。)

std::future<void> future2 = 
    runAsyncTerminateOnException([&foo]{ return foo.print(2); });

wandbox示例

我找到了C 17的解决方案。它仅在我们不使用自动返回类型的RunterMinateOnexception()的返回类型的情况下起作用。

template<class Fn, class... Args>
inline std::result_of_t<Fn&&(Args&&...)> runTerminateOnException(Fn&& fn, Args&&... args) {
    try {
        return std::invoke(std::forward<Fn>(fn), std::forward<Args>(args)...);
    } catch (...) {
        std::terminate();
    }
}
template<class Fn, class... Args>
inline auto runAsyncTerminateOnException(Fn&& fn, Args&&... args) {
    return std::async(std::launch::async, runTerminateOnException<Fn, Args&&...>, std::forward<Fn>(fn), std::forward<Args>(args)...);
}