我正在尝试实现简单的ScopedExit类。这是代码:#include <iostream>#include <functional>template<class R, class... Args>class ScopedExit{public: ScopedExit(std::function<R(Args...)> exitFunction) { exitFunc_ = exitFunction; } ~ScopedExit() { exitFunc_(); }private: std::function<R(Args...)> exitFunc_;};template<>class ScopedExit<void>{public: ScopedExit(std::function<void ()> exitFunction) { exitFunc_ = exitFunction; } ~ScopedExit() { exitFunc_(); }private: std::function<void ()> exitFunc_;};void foo(){ std::cout << "foo() called\n";}class Bar{public: void BarExitFunc(int x, int y) { std::cout << "BarExitFunc called with x =" << x << "y = " << y << "\n"; }};int main(){ Bar b; std::cout << "Register scoped exit func\n"; { ScopedExit<void, int, int> exitGuardInner(std::bind(&Bar::BarExitFunc, &b, 18, 11)); } ScopedExit exitGuardOutter(foo); std::cout << "About to exit from the scope\n"; return 0;}因此,有两个问题:如何将导出的函数参数传递给它?例如,我将BarExitFunc与两个整数参数绑定(bind):18和11。那么如何将其传递给析构函数中的exitFunc_?我想我需要类似std::forward 的invoke函数。 gcc 4.7.2(来自ideone.com)抱怨exitGuardOutter。它说:prog.cpp:60:16: error: missing template arguments before ‘exitGuardOutter’prog.cpp:60:16: error: expected ‘;’ before ‘exitGuardOutter’提前致谢。 (adsbygoogle = window.adsbygoogle || []).push({}); 最佳答案 How to pass exit's function arguments to it? For example, I bind BarExitFunc with two integer arguments: 18 and 11. So how can I pass it to the exitFunc_ in the destructor?我看不出有任何理由在析构函数中的调用时将参数传递给exitFunc_。无论您做什么,都必须在ScopedExit构造函数中预先提供这些参数。最直接的方法就是简单地在定义站点上使用function<R()>和bind任何必需的参数,就像您已经在做的那样:ScopedExit<R> guard(std::bind(someFunction, someArg, otherArg));这使您完全摆脱了可变参数模板参数,并大大简化了模板。现在,如果麻烦的是您必须键入std::bind,而您宁愿使用这样的语法:ScopedExit<R> guard(someFunction, someArg, otherArg);的确,我不明白这一点,因为它使模板更加复杂,但是为什么不呢……只要在构造函数本身中绑定(bind)/转发参数并仍然存储function<R()>:template<typename... Args>ScopedExit(std::function<R(Args...)> exitFunction, Args&&... args){ exitFunc_ = std::bind(exitFunction, std::forward<Args>(args)...);}现在,即使没有要绑定(bind)的参数,您也可以系统地对函数进行bind编码,因此您可能希望专门化您的类,以在没有参数的情况下避免这种无用的bind。这留作练习。 gcc 4.7.2 (from ideone.com) complains about exitGuardOutter这是因为foo不是std::function,并且编译器无法推断出正确的模板参数。正如@ForEveR所提到的,您可以将防护变量定义为ScopedExit<void> guard(foo);。或者,将其全部包装成,并牢记我首先说的内容(最好将bind留在模板中,并在卫兵的定义站点中使用),您可以在构造函数中摆脱std::function并归纳为任何仿函数(顺便说一句,这是标准库在需要函子/回调时的工作方式)。对于存储,您可以只使用std::function<void()>,因为它也接受非空返回类型:class ScopedExit{public: template<typename Functor> ScopedExit(Functor exitFunction) { exitFunc_ = exitFunction; } ~ScopedExit() { exitFunc_(); }private: std::function<void()> exitFunc_;};int foo() { return 0; }struct Bar { void bye(int, int) {}};struct Baz { void operator ()() {}};int main() { const std::string what = "lambda!"; ScopedExit guard1([&]() { std::cout << "yay a " << what << std::endl; }); ScopedExit guard2(foo); // note how std::function<void()> accepts non-void return types Bar b; ScopedExit guard3(std::bind(&Bar::bye, &b, 1, 2)); ScopedExit guard4(Baz());}请注意,您原来的可变参数模板类现在如何变成仅具有模板构造函数的灵活非模板类,该模板化构造函数的模板参数是自动推导的,并且几乎可以[请参见以下注意事项]接受您可以考虑的任何一种仿函数。 注意:我说了几乎所有函子,因为这不适用于默认参数:void foobar(int = 0) {}ScopedExit guard5(foobar); // error: too few arguments to function即使您直接存储的是Functor而不是std::function<void()>,您也无论如何都无法使用默认参数(即使使用默认参数,foobar的签名仍然是void(int)),因此始终必须在定义站点,如下所示:void foobar(int = 0) {}ScopedExit guard5([]() { foobar(); });关于c++ - ScopedExit实现:将参数传递给函数对象,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16917821/ (adsbygoogle = window.adsbygoogle || []).push({});
10-09 13:37