Scoped Pairs of functions?
Hi all, I'm on a project which uses a C++ compiler, but with a lot of C-isms. One of those is that there are objects with pairs of functions which allocate/deallocate resources. I don't have time to fix all of the design issues with the classes that do this (yet), but within one compilation unit I'd like to remove the chance for leaks. So - if I wanted to use boost types to wrap around 2 functions f() and g(), where each function - has a void or primitive return type - takes zero or 1 argument - where f() is called at some point in a scope, and then g() is called *on exiting the scope *from which f() is called and only if f() doesn't throw.. - has its return value ignored. [Gahh....] Is there a boost::bind (or lambda) expression that I can wrap in a type? I'm not adverse to using several template parameters. If it were just nullary functions I could just use: struct Reference {}; struct TypeWrapper{}; // Signify something like shared_ptr, a T which wraps around a pointer to an object of the type containing the functions, where T has a typedef value_type to refer to the wrapped type, and a get() to obtain a pointer to the wrapped pointer. template<class T, type R1, type R2, class P = Reference> struct ScopedDuals { typedef R1 (T::*f_t)(); typedef R2 (T::*g_t)(); ScopedDuals(T&t, f_t f, g_t g) : t_(t), g_(g) { (t_.f)(); } ~ScopedDuals() { (t_.*g_)(); } private: T& t_; g_t g_; }; template<class T, type R1. type R2> struct ScopedDuals<T, R1, R2, TypeWrapper> { typedef typname T::value_type Inner_t; typedef R1 (Inner_t::*f_t)(); typedef R2 (Inner_t::*g_t)(); ScopedDuals(T&t, f_t f, g_t g) : t_(t), g_(g) { (t_.get()->*f)(); } ~ScopedDuals() { (t_.get()->*g_)(); } private: T& t_; g_t g_; }; How do I generalize to include the possibility of a single argument? and.... does anyone have a better suggestion for a name than "ScopedDuals"? While *I *think it's precise, it may not be useful to my teammates. thanks, Brian
On Wed, Aug 17, 2011 at 10:49 AM, Brian Allison <brian.w.allison@gmail.com> wrote:
I'm on a project which uses a C++ compiler, but with a lot of C-isms. One of those is that there are objects with pairs of functions which allocate/deallocate resources. I don't have time to fix all of the design issues with the classes that do this (yet), but within one compilation unit I'd like to remove the chance for leaks.
So - if I wanted to use boost types to wrap around 2 functions f() and g(), where each function
has a void or primitive return type takes zero or 1 argument where f() is called at some point in a scope, and then g() is called on exiting the scope from which f() is called and only if f() doesn't throw.. has its return value ignored. [Gahh....]
Is there a boost::bind (or lambda) expression that I can wrap in a type?
How do I generalize to include the possibility of a single argument?
The following works for me with gcc 4.0.1 (yeah, I know, old compiler): #include <iostream> #include <boost/function.hpp> #include <boost/bind.hpp> void acquire_fixed() { std::cout << "Acquiring fixed resource\n"; } void release_fixed() { std::cout << "Releasing fixed resource\n"; } void acquire(const std::string& resource) { std::cout << "Acquiring " << resource << '\n'; } void release(const std::string& resource) { std::cout << "Releasing " << resource << '\n'; } class ScopedResource { public: typedef boost::function<void()> ResourceFunc; ScopedResource(const ResourceFunc& acq, const ResourceFunc& rel): mRelease(rel) { acq(); } virtual ~ScopedResource() { mRelease(); } private: ResourceFunc mRelease; }; int main(int argc, char *argv[]) { { ScopedResource fixed(acquire_fixed, release_fixed); std::cout << "during lifespan of 'fixed'\n"; } { ScopedResource something(boost::bind(acquire, "something"), boost::bind(release, "something")); std::cout << "during lifespan of 'something'\n"; } return 0; }
On Thu, Aug 18, 2011 at 1:04 PM, Nat Linden <nat@lindenlab.com> wrote:
On Wed, Aug 17, 2011 at 10:49 AM, Brian Allison <brian.w.allison@gmail.com> wrote:
I'm on a project which uses a C++ compiler, but with a lot of C-isms. One of those is that there are objects with pairs of functions which allocate/deallocate resources. I don't have time to fix all of the design issues with the classes that do this (yet), but within one compilation unit I'd like to remove the chance for leaks.
So - if I wanted to use boost types to wrap around 2 functions f() and g(), where each function
has a void or primitive return type takes zero or 1 argument where f() is called at some point in a scope, and then g() is called on exiting the scope from which f() is called and only if f() doesn't throw.. has its return value ignored. [Gahh....]
Is there a boost::bind (or lambda) expression that I can wrap in a type?
How do I generalize to include the possibility of a single argument?
The following works for me with gcc 4.0.1 (yeah, I know, old compiler):
#include <iostream> #include <boost/function.hpp> #include <boost/bind.hpp>
void acquire_fixed() { std::cout << "Acquiring fixed resource\n"; }
void release_fixed() { std::cout << "Releasing fixed resource\n"; }
void acquire(const std::string& resource) { std::cout << "Acquiring " << resource << '\n'; }
void release(const std::string& resource) { std::cout << "Releasing " << resource << '\n'; }
class ScopedResource { public: typedef boost::function<void()> ResourceFunc; ScopedResource(const ResourceFunc& acq, const ResourceFunc& rel): mRelease(rel) { acq(); }
virtual ~ScopedResource() { mRelease(); }
private: ResourceFunc mRelease; };
int main(int argc, char *argv[]) { { ScopedResource fixed(acquire_fixed, release_fixed); std::cout << "during lifespan of 'fixed'\n"; } { ScopedResource something(boost::bind(acquire, "something"), boost::bind(release, "something")); std::cout << "during lifespan of 'something'\n"; } return 0; } _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Is there a way to generalize the return type so that ScopedResource could be in a library and the user could use it for pairing two functions that have int and void return types respectively? I'm not familiar with boost::function, so I don't know if I could mod the class and typedef to: template *<type R1 = void, type R2 = void>* class ScopedResource { public:* typedef boost::function<R1()> ResourceFunc1; * // will this work?* typedef boost::function<R2()> ResourceFunc2; * // will this work?* * and the object declarations as { ScopedResource fixed(acquire_fixed, release_fixed); std::cout << "during lifespan of 'fixed'\n"; } { ScopedResource*<void, int>* something(*f_that_returns_int, g_with_void_return*); std::cout << "during lifespan of 'something'\n"; }
On Fri, Aug 19, 2011 at 7:00 AM, Brian Allison <brian.w.allison@gmail.com> wrote:
Is there a way to generalize the return type so that ScopedResource could be in a library and the user could use it for pairing two functions that have int and void return types respectively?
? I don't think that's necessary. The following still works for me (g++): #include <iostream> #include <boost/function.hpp> #include <boost/bind.hpp> void acquire_fixed() { std::cout << "Acquiring fixed resource\n"; } int iacquire_fixed() { int ret(34); std::cout << "Acquiring fixed resource, returning " << ret << '\n'; return ret; } void release_fixed() { std::cout << "Releasing fixed resource\n"; } void acquire(const std::string& resource) { std::cout << "Acquiring " << resource << '\n'; } int iacquire(const std::string& resource) { int ret(17); std::cout << "Acquiring " << resource << ", returning " << ret << '\n'; return ret; } void release(const std::string& resource) { std::cout << "Releasing " << resource << '\n'; } class ScopedResource { public: typedef boost::function<void()> ResourceFunc; ScopedResource(const ResourceFunc& acq, const ResourceFunc& rel): mRelease(rel) { acq(); } virtual ~ScopedResource() { mRelease(); } private: ResourceFunc mRelease; }; int main(int argc, char *argv[]) { { ScopedResource fixed(acquire_fixed, release_fixed); std::cout << "during acquire_fixed()\n"; } { ScopedResource fixed(iacquire_fixed, release_fixed); std::cout << "during iacquire_fixed()\n"; } { ScopedResource something(boost::bind(acquire, "something"), boost::bind(release, "something")); std::cout << "during acquire('something')\n"; } { ScopedResource something(boost::bind(iacquire, "something"), boost::bind(release, "something")); std::cout << "during iacquire('something')\n"; } return 0; }
participants (2)
-
Brian Allison
-
Nat Linden