Question

I'm working on a resource management class and want to have the user provide a functor to a "ReleaseResource" method as part of the resource manager's constructor. From there when a resource is requested that functor will be provided as the deleter for the shared_ptr that I will be returning so that the appropriate method will be called when the resource is no longer used.

The problem I'm running into that this requires me to store the functor in my class, and I'm not entirely sure how to do that. Typically when using a functor you template the function like so:

template<class MyFunctor> MyMethod(MyFunctor f) {
    f();
}

Which is great if you intend to use the functor in the scope of that function, but since the template goes out of scope with the function I'm not sure how you would specify a variable of the appropriate type to store the functor for later use.

Can anyone point me in the right direction here?

Was it helpful?

Solution

template<class MyFunctor> MyMethod(MyFunctor f) {
    boost::function<void()> g = f;
    g();
}

The type you pass to boost::function is the function type. For example, int(bool, char) is the type of a function returning int and taking a bool and a char. That said, if you want to construct the shared_ptr right away, you don't need to store the functor somewhere (boost::function requires the new operator for that, even though for very small functors, it will use special tricks to only use stack allocation (small buffer optimization)):

template<class MyFunctor> MyMethod(MyFunctor f) {
    boost::shared_ptr<T> ptr(new T, f);
}

boost::function is part of tr1 and will be part of the next official C++ Standard. Example:

struct Manager {
    template<typename Deleter>
    Manager(Deleter d) 
        :deleter(d) {

    }

    boost::shared_ptr<Resource> allocate() {
        ...
        return boost::shared_ptr<Resource>(resource, deleter);
    }

private:
    boost::function<void(Resource *)> deleter;
};

OTHER TIPS

There are two ways, both of which biol down to templating the class.

template <MyFunctor>
class MyClass
{
   MyFunctor   func;
  public:
    MyClass(MyFunctor f) :func(f)
    { }


    MyMethod() 
   {
       func();
   }
}

This would require you to know the type of the functor. To avoid that, we can use a factory:

 template<MyFunctor>
 MyClass<MyFunctor>  MakeFunctorClass(MyFunctor f)
 {     
     return MyClass<MyFunctor>(f);       
 }

Alternately, since in all likelihood, most of the functor signature will be the same, with only a small part changing, we could use that:

template <MyType>
class MyClass
{
   typedef std::binary_function<MyType, MyType, bool>  MyFunctor;
   MyFunctor func;
  public:


    MyMethod(MyFunctor f) 
   {
       func = f;
       func();
   }
}

This makes usage a bit simpler:

 bool AreEqual(int, int); 
 MyClass<int> myc;
 myc.MyMethod(AreEqual);

at the expensive of a trickier definition (i.e., I don't guarantee that the binary_function typedef I gave will work)

Not sure if this would help, but be aware that boost::shared_ptr has constructor overrides which allow the user to include a custom de-allocation (and custom allocator, if desired). This might be sufficient for what you need (it's designed with that in mind, if I'm reading your use-case correctly).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top