Bai*_*ker 3 c++ closures c++17
假设我有一些包装函数,我想做一些设置,调用回调(并保存其结果),做一些清理,然后返回回调返回的内容:
#include <functional>
#include <utility>
template<class F, typename... Args>
decltype(auto) wrap(F&& func, Args&... args) {
// Do some stuff before
auto result = std::invoke(std::forward<decltype(func)>(func),
std::forward<Args>(args)...);
// Do some stuff after
return result;
}
Run Code Online (Sandbox Code Playgroud)
一个实际的例子是一个计时器实用程序函数,它返回函数调用的经过时间及其返回值(也许在元组中).
这样的函数适用于具有返回类型的callables:
void foo() {
auto a = 1;
wrap([](auto a) { return 1; }, a);
}
Run Code Online (Sandbox Code Playgroud)
但是使用void返回类型的可调用,在模板特化期间编译器抱怨auto result具有不完整类型void:
void foo() {
auto a = 1;
wrap([](auto a) {}, a);
}
Run Code Online (Sandbox Code Playgroud)
这当然是有道理的,因为虽然你可以return void(),但你不能将它存储在一个变量中.
我想wrap为两种类型的callables工作.我试图用std::function两个签名wrap:
template<class T, typename... Args> decltype(auto) wrap(std::function<T(Args...)>, Args&... args)template<typename... Args> decltype(auto) wrap(std::function<void(Args...)>, Args&... args)第一个将继续匹配不void返回的callables ,但后者无法匹配返回类型的callables void.
有没有办法在返回类型void和不可void调用的情况下进行包装工作?
我喜欢解决这个问题的方法是定期无效.好吧,我们实际上没有适当的常规void,但我们可以制作我们自己的Void常规类型,有点像void.然后提供一个invoke了解它的包装器.
最短的版本(该博客中有更多细节):
struct Void { };
template <typename F, typename ...Args,
typename Result = std::invoke_result_t<F, Args...>,
std::enable_if_t<!std::is_void_v<Result>, int> = 0>
Result invoke_void(F&& f, Args&& ...args) {
return std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
}
// void case
template <typename F, typename ...Args,
typename Result = std::invoke_result_t<F, Args...>,
std::enable_if_t<std::is_void_v<Result>, int> = 0>
Void invoke_void(F&& f, Args&& ...args) {
std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
return Void();
}
Run Code Online (Sandbox Code Playgroud)
这使您可以在原始代码中执行以下操作:
template<class F, typename... Args>
decltype(auto) wrap(F&& func, Args&... args) {
// Do some stuff before
auto result = invoke_void(std::forward<decltype(func)>(func),
std::forward<Args>(args)...);
// Do some stuff after
return result;
}
Run Code Online (Sandbox Code Playgroud)
即使func返回,这也有效void.
| 归档时间: |
|
| 查看次数: |
153 次 |
| 最近记录: |