【发布时间】:2018-07-21 08:14:50
【问题描述】:
假设我有一些包装函数,我想在其中进行一些设置,调用回调(并保存其结果),进行一些清理,然后返回回调返回的内容:
#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;
}
一个实际的例子是一个计时器实用函数,它返回函数调用的经过时间以及它的返回值(也许在一个元组中)。
这样的函数适用于具有返回类型的可调用对象:
void foo() {
auto a = 1;
wrap([](auto a) { return 1; }, a);
}
但是对于返回类型为 void 的可调用对象,在模板特化期间,编译器会抱怨 auto result 的 void 类型不完整:
void foo() {
auto a = 1;
wrap([](auto a) {}, a);
}
这当然是有道理的,因为while you can return void(),你不能将它存储在变量中。
我希望wrap 能够同时处理这两种可调用对象。我尝试使用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 返回的可调用对象,但后者无法匹配具有返回类型void 的那些。
有没有办法让 wrap 在返回类型 void 和非void 可调用情况下都起作用?
【问题讨论】:
-
我没有时间给出完整的答案,但这听起来像是
std::optional用例。