gpt4 book ai didi

c++ - 包装一个可能返回 void 的可调用对象

转载 作者:太空狗 更新时间:2023-10-29 20:08:54 24 4
gpt4 key购买 nike

假设我有一些包装函数,我想在其中进行一些设置、调用回调(并保存其结果)、进行一些清理,然后返回回调返回的内容:

#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::functionwrap两个签名:

  1. template<class T, typename... Args> decltype(auto) wrap(std::function<T(Args...)>, Args&... args)
  2. template<typename... Args> decltype(auto) wrap(std::function<void(Args...)>, Args&... args)

其中第一个将继续匹配具有非 void 的可调用对象返回,但后者无法匹配返回类型为 void 的那些.

有没有办法让 wrap 在返回类型 void 中都起作用?和非 void可调用案例?

最佳答案

我喜欢用regular 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();
}

这让您可以在您的原始代码中执行:

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;
}

这有效,即使 func 返回 void

关于c++ - 包装一个可能返回 void 的可调用对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51454183/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com