2009-01-23 30 views
6

Tôi đang làm việc trên một lớp quản lý tài nguyên và muốn người dùng cung cấp một hàm functor cho một phương thức "ReleaseResource" như một phần của hàm tạo của trình quản lý tài nguyên. Từ đó khi một tài nguyên được yêu cầu functor sẽ được cung cấp như là deleter cho shared_ptr mà tôi sẽ quay trở lại để phương thức thích hợp sẽ được gọi khi tài nguyên không còn được sử dụng nữa.Giữ lại các functors dưới dạng biến

Sự cố mà tôi đang gặp phải là điều này yêu cầu tôi lưu trữ hàm trong lớp của mình và tôi không hoàn toàn chắc chắn cách thực hiện điều đó. Thông thường khi sử dụng một functor bạn template chức năng như vậy:

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

Đó là tuyệt vời nếu bạn có ý định sử dụng các functor trong phạm vi chức năng đó, nhưng kể từ khi mẫu đi ra khỏi phạm vi với chức năng tôi không chắc chắn làm thế nào bạn sẽ chỉ định một biến của loại thích hợp để lưu trữ các functor để sử dụng sau này.

Có ai có thể chỉ cho tôi đúng hướng ở đây không?

Trả lời

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

Loại bạn chuyển đến boost::function là loại chức năng. Ví dụ, int(bool, char) là loại hàm trả về int và lấy một bool và char. Điều đó nói rằng, nếu bạn muốn xây dựng shared_ptr ngay lập tức, bạn không cần lưu trữ functor ở đâu đó (boost::function yêu cầu toán tử new cho điều đó, mặc dù đối với các functors rất nhỏ, nó sẽ sử dụng các thủ thuật đặc biệt để chỉ sử dụng phân bổ stack (tối ưu hóa nhỏ đệm)):

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

tăng :: chức năng là một phần của tr1 và sẽ là một phần của chính thức tiếp theo C++ Standard. Ví dụ:

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

Tuyệt vời! Điều này thật đúng với gì mà tôi đã tìm kiếm. Cảm ơn nhiều! – Toji

0

Không chắc chắn nếu điều này sẽ giúp ích, nhưng lưu ý rằng tăng :: shared_ptr có phần ghi đè của hàm tạo cho phép người dùng bao gồm phân bổ tùy chỉnh (và trình phân bổ tùy chỉnh, nếu muốn). Điều này có thể là đủ cho những gì bạn cần (nó được thiết kế với ý nghĩ đó, nếu tôi đang đọc trường hợp sử dụng của bạn một cách chính xác).

+0

Tôi đã biết điều này và đang sử dụng nó trong ví dụ trên. Những gì tôi cần biết là làm thế nào để lưu trữ các tham số mà bạn vượt qua nó. – Toji

3

Có hai cách, cả hai đều biol xuống để tạo khuôn mẫu cho lớp học.

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


    MyMethod() 
    { 
     func(); 
    } 
} 

Điều này sẽ yêu cầu bạn biết loại trình rút gọn. Để tránh điều đó, chúng ta có thể sử dụng một nhà máy:

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

Cách khác, vì trong tất cả các khả năng, hầu hết các chữ ký functor sẽ giống nhau, chỉ có một thay đổi một phần nhỏ, chúng ta có thể sử dụng:

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


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

Điều này làm cho việc sử dụng đơn giản hơn một chút:

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

tại tốn kém của một định nghĩa phức tạp hơn (ví dụ, tôi không đảm bảo rằng các binary_function typedef tôi đã sẽ làm việc)

+0

Ngoại trừ việc đây không phải là cách 'binary_function' hoạt động. binary_function là một kiểu-đặc điểm-cho-thuộc tính, không phải là một giao diện.nó không có toán tử áp dụng, do đó câu lệnh 'func()' không hợp lệ, ngay cả khi bạn cung cấp đối số. xem câu trả lời khác về hàm tăng :: chức năng hoặc tr1 ::. – Aaron

+0

Đó là lý do tại sao tôi đặc biệt nói "Tôi không đảm bảo rằng binary_function typedef tôi đã đưa ra sẽ hoạt động". Tôi đã khá chắc chắn nó sẽ không, nhưng tôi biết có một loại tiêu chuẩn mà có thể. –

Các vấn đề liên quan