2009-01-23 15 views
6

Pracuję nad klasą zarządzania zasobami i chcę, aby użytkownik udostępnił funktorowi metodę "ReleaseResource" jako część konstruktora menedżera zasobów. Stamtąd, gdy zasób zostanie zażądany, funktor będzie dostarczony jako delter dla shared_ptr, który zwrócę, aby odpowiednia metoda została wywołana, gdy zasób nie jest już używany.Zachowanie funktorów jako zmiennych

Problem, który napotykam, wymaga ode mnie przechowywania funktora w klasie i nie jestem do końca pewien, jak to zrobić. Zazwyczaj podczas korzystania z funktor ty szablon funkcja tak:

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

co jest dobre, jeśli masz zamiar używać funktor w zakresie tej funkcji, ale ponieważ szablon wychodzi z zakresu z funkcją jestem nie wiem, jak określić zmienną odpowiedniego typu do przechowywania funktora do późniejszego wykorzystania.

Czy ktoś może wskazać mi właściwy kierunek?

Odpowiedz

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

Typ przekazywany do boost::function jest typem funkcji. Na przykład int(bool, char) jest typem funkcji zwracającej int i przyjmującej bool i char. To powiedziawszy, jeśli chcesz od razu zbudować shared_ptr, nie musisz przechowywać funktora gdzieś (boost::function wymaga do tego operatora new, mimo że dla bardzo małych funktorów użyje specjalnych trików, aby używać tylko alokacji stosu (mały bufor optimization)):

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

boost :: funkcja jest częścią tr1 i będzie częścią kolejnego urzędnika C++ standard. Przykład:

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

Doskonale! Właśnie tego szukałem. Dziękuję Ci bardzo! – Toji

0

Nie jestem pewien, czy to pomogłoby, ale należy pamiętać, że funkcja boost :: shared_ptr ma nadpisania konstruktorów, które pozwalają użytkownikowi uwzględnić niestandardową de alokację (i niestandardowy przydział, jeśli jest to wymagane). To może wystarczyć dla tego, czego potrzebujesz (jest to zaprojektowane z myślą o tym, jeśli dobrze czytam Twój przypadek użycia).

+0

Jestem już tego świadomy i używam go w powyższym przykładzie. Muszę wiedzieć, jak zapisać parametr, który do niego przekazujesz. – Toji

3

Istnieją dwa sposoby, oba z nich skierowane na szablonowanie klasy.

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


    MyMethod() 
    { 
     func(); 
    } 
} 

Wymagałoby to znajomości rodzaju funktora. Aby tego uniknąć, możemy użyć fabryczne:

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

Alternatywnie, ponieważ według wszelkiego prawdopodobieństwa, większość z podpisem funktora będzie taki sam, tylko z małą zmiany części, możemy użyć tego:

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


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

To sprawia, że ​​użycie nieco prostsze:

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

na drogie z trudniejsze definicji (tzn ja nie gwarantują, że binary_function typedef dałem zadziała)

+0

Tyle tylko, że nie działa w ten sposób "binary_function". binary_function jest atrybutem typu-dawania cech, a nie interfejsem.nie ma operatora stosującego, więc instrukcja "func()" jest nieprawidłowa, nawet jeśli podajesz argumenty. zobacz inną odpowiedź dotyczącą funkcji boost :: function lub tr1 :: function. – Aaron

+0

Dlatego właśnie powiedziałem: "Nie gwarantuję, że podana przeze mnie funkcja binary_function zadziała". Byłem prawie pewien, że nie, ale wiedziałem, że istnieje standardowy typ, który by to zrobił. –

Powiązane problemy