2009-01-23 9 views
6

Estoy trabajando en una clase de gestión de recursos y quiero que el usuario proporcione un funtor a un método "ReleaseResource" como parte del constructor del administrador de recursos. A partir de allí, cuando se solicite un recurso, se proporcionará el functor como el eliminador para el shared_ptr que voy a devolver para que se invoque el método apropiado cuando el recurso ya no se utilice.Fungibles de retención como variables

El problema con el que me estoy encontrando es que esto requiere que almacene el funtor en mi clase, y no estoy del todo seguro de cómo hacerlo. Por lo general cuando se utiliza una plantilla de funtor que la función de este modo:

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

que es grande si usted tiene la intención de utilizar el funtor en el ámbito de esa función, pero dado que la plantilla se sale del ámbito de la función que estoy no estoy seguro de cómo se especificaría una variable del tipo apropiado para almacenar el funtor para su uso posterior.

¿Puede alguien señalarme en la dirección correcta aquí?

Respuesta

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

El tipo que pase a boost::function es el tipo de función. Por ejemplo, int(bool, char) es el tipo de una función que devuelve int y toma un bool y un char. Dicho eso, si quiere construir el shared_ptr de inmediato, no necesita almacenar el functor en algún lugar (boost::function requiere el operador new para eso, aunque para funtores muy pequeños, usará trucos especiales para usar solo la asignación de pila (optimización pequeño búfer)):

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

impulso :: función es parte de tr1 y formará parte de la próxima oficial de C++ estándar. Ejemplo:

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; 
}; 
+0

¡Excelente! Esto es exactamente lo que estaba buscando. ¡Muchas gracias! – Toji

0

No estoy seguro si esto ayudaría, pero tenga en cuenta que boost :: shared_ptr tiene modificaciones de constructor que permiten al usuario incluir una desasignación personalizada (y un asignador personalizado, si lo desea). Esto podría ser suficiente para lo que necesita (está diseñado con eso en mente, si estoy leyendo su caso de uso correctamente).

+0

Ya conozco esto y lo estoy usando en el ejemplo anterior. Lo que necesito saber es cómo almacenar el parámetro que le pasas. – Toji

3

Hay dos maneras, ambos de los cuales Biol hacia abajo para templating la clase.

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


    MyMethod() 
    { 
     func(); 
    } 
} 

Esto requeriría que usted conozca el tipo de functor. Para evitar esto, podemos usar una fábrica:

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

Como alternativa, ya que, con toda probabilidad, la mayor parte de la firma funtor será el mismo, con sólo un pequeño cambio parte, podríamos usar esa:

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


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

Esto hace que el uso de un poco más simple:

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

en la cara de una definición más complicado (es decir, no garantizo que el binary_function typedef me dio funcionará)

+0

Excepto que no es así como funciona 'binary_function'. binary_function es un atributo type-trait-giving, no una interfaz.no tiene un operador de aplicación, por lo que la declaración 'func()' no es válida, incluso si proporciona argumentos. ver otra respuesta sobre boost :: function, o tr1 :: function. – Aaron

+0

Por eso dije específicamente "No garantizo que funcione la función binary typedef I dio". Estaba bastante seguro de que no sería así, pero sabía que había un tipo estándar que lo haría. –

Cuestiones relacionadas