【发布时间】:2020-08-31 12:20:51
【问题描述】:
#include <iostream>
#include <string>
template<typename Func>
class FuncWrapper {
Func func;
std::string name;
public:
FuncWrapper(Func func, std::string name) : func(func), name(std::move(name)) {}
template<typename ...Args>
auto operator()(Args ...args) {
std::cout << "Entering " + name + '\n';
auto ret = func(args...);
std::cout << "Exiting " + name + "\n\n";
return ret;
}
};
template<typename Func>
auto makeFuncWrapper(Func func, std::string name) {
return FuncWrapper<Func>(func, name);
}
int main() {
auto helloWorld = []() { std::cout << "Hello World\n"; };
auto addTwoNums = [](int a, int b) { std::cout << "Adding numbers...\n"; return a + b; };
// makeFuncWrapper(helloWorld, "helloWorld")(); // error: 'void ret' has incomplete type.
std::cout << makeFuncWrapper(addTwoNums, "addTwoNums")(4, 5) << '\n';
}
此类FuncWrapper 工作正常,并为传递的函数添加了额外的功能,直到传递的函数是返回void 的函数。我收到ret 的类型不完整的错误。即使使用返回类型为void 的函数,还有其他方法可以使它工作吗?我知道我不能有void 变量,但在这里,ret 的唯一目的是在函数完成后返回,并且不会以错误的方式使用它。是否有解决方案或一些解决方法使其工作?有没有更好的方法来实现包装任何函数的函数包装器?
【问题讨论】:
-
取决于 ypu 使用什么标准,您要么创建一个 SFINAE 方案,要么使用
if constrexpr与“包装器”周围的“包装器”,这将为无效和非无效结果提供服务。另外,如果您想接受其他 callable ,例如lsmbdas,您也必须单独为它们服务。你的包装看起来像std::invoke,它的样板代码很大。 -
注意:lambda表达式的结果不是一个函数,它是一个定义了
operator()的类类型的实例。
标签: c++ templates wrapper void