TL;医生:
- 工作版本:https://godbolt.org/z/fsxEeGf6W
- 损坏版本(为什么?):https://godbolt.org/z/KoooxsqoW
我正在编写一个实用函数,它在捕获所有异常的同时 Package std::async
。
#include <functional>
#include <future>
#include <iostream>
#include <string>
#include <thread>
namespace Async {
namespace detail {
template <typename F, typename... Args>
std::invoke_result_t<F, Args...> RunWithLogging(std::string label, F&& f,
Args&&... args) {
try {
return std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
} catch (std::exception& ex) {
std::cout << label << "Exception escaped thread \"" << label
<< "\": " << ex.what();
throw;
} catch (...) {
std::cout << label << "Exception escaped thread \"" << label
<< "\": (non-standard exception type)";
throw;
}
}
} // namespace detail
/// Like std::async(std::launch::async, f, args...):
/// - Catches and logs any escaped exceptions
/// - Returned future joins the thread on destructor
template <typename F, typename... Args>
[[nodiscard]] std::future<std::invoke_result_t<F, Args...>> Launch(
std::string label, F&& f, Args&&... args) {
return std::async(
std::launch::async, [label = std::move(label), f = std::forward<F>(f),
... args = std::forward<Args>(args)]() mutable {
return detail::RunWithLogging(std::move(label), std::forward<F>(f),
std::forward<Args>(args)...);
});
}
} // namespace Async
我想我可以节省几行代码,只使用一个使用async的参数传递签名的函数指针,而不用那个双转发可变lambda:
template <typename F, typename... Args>
[[nodiscard]] std::future<std::invoke_result_t<F, Args...>> Launch(
std::string label, F&& f, Args&&... args) {
return std::async(std::launch::async, &detail::RunWithLogging,
std::move(label), std::forward<F>(f),
std::forward<Args>(args)...);
;
}
由于以下原因,该代码无法编译:
C:\...\lib\Async\Thread.h(33,15): error C2672: 'async': no matching overloaded function found [C:\...\build\lib\Async\AsyncTest.vcxproj]
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.34.31933\include\future(1535,81): message : could be 'std::future<_Select_invoke_traits<decay<_Ty>::type,decay<_ArgTypes>::type...>::type> std::async(_Fty &&,_ArgTypes &&...)' [C:\...\build\lib\Async\AsyncTest.vcxproj]
C:\...\lib\Async\Thread.h(33,15): message : 'std::future<_Select_invoke_traits<decay<_Ty>::type,decay<_ArgTypes>::type...>::type> std::async(_Fty &&,_ArgTypes &&...)': could not deduce template argument for '_ArgTypes &&' from 'overloaded-function' [C:\...\build\lib\Async\AsyncTest.vcxproj]
C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.34.31933\include\future(1522,81): message : or 'std::future<_Select_invoke_traits<decay<_Ty>::type,decay<_ArgTypes>::type...>::type> std::async(std::launch,_Fty &&,_ArgTypes &&...)' [C:\...\build\lib\Async\AsyncTest.vcxproj]
C:\...\lib\Async\Thread.h(32,47): message : 'std::future<_Select_invoke_traits<decay<_Ty>::type,decay<_ArgTypes>::type...>::type> std::async(std::launch,_Fty &&,_ArgTypes &&...)': could not deduce template argument for '_Fty' [C:\...\build\lib\Async\AsyncTest.vcxproj]
C:\...\lib\Async\ThreadTest.cpp(24,57): message : see reference to function template instantiation 'std::future<int> Async::Launch<int(__cdecl *)(int),int>(std::string,F &&,int &&)' being compiled [C:\...\build\lib\Async\AsyncTest.vcxproj]
with
[
F=int (__cdecl *)(int)
]
我做错什么了?我试过了:
- 将
std::decay_t<>
添加到invoke_result_t<...>
的参数 - 显式指定
RunWithLogging
的模板参数 &detail::RunWithLogging
或detail::RunWithLogging
- 使用
auto
返回类型
1条答案
按热度按时间ttisahbt1#
我认为问题在于引用没有被传递给线程,并且
std::async
的函数参数没有被完全专用化。我专门化了
detail::RunWithLogging
,并按值传递标签:然后,我将
std::ref
添加到lambda函数中。最后,我用
std::ref
Package 了hi
,这修复了所有编译问题。Lambda很好,因为它们无需使用
std::ref
即可捕获引用。有关详细信息,请参见this other post。