#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
是要在函数完成后返回的,不会用错。有什么办法或变通的办法让它工作吗?有什么更好的方法来实现一个可以封装任何函数的函数封装器吗?
你可以使用Raii。
template<typename ...Args>
auto operator()(Args ...args) {
struct EndScope {
std::string& name;
~EndScope() { std::cout << "Exiting " + name + "\n\n"; }
} endScope(name);
std::cout << "Entering " + name + '\n';
return func(args...);
}
你可以进一步用 std::uncaught_exceptions
请看 raii-way to get-errors-that-are-caught-during-destroying(破坏过程中捕获的错误)。