2011-12-05 38 views
8

Tôi có một lớp CMyVector chứa một vector con trỏ tới các đối tượng CMyClass và tôi có một số chức năng "tìm" để tìm các phần tử theo các tiêu chí khác nhau. Ví dụ: tôi có:Cách chuyển vị ngữ làm tham số chức năng

CMyClass* CMyVector::FindByX(int X); 
CMyClass* CMyVector::FindByString(const CString& str); 
CMyClass* CMyVector::FindBySomeOtherClass(CSomeOtherClass* ptr); 
// Other find functions... 

Lúc đầu, chúng được thực hiện dưới dạng vòng, di chuyển vectơ, tìm kiếm phần tử khớp với X, str, ptr hoặc bất kỳ thứ gì. Vì vậy, tôi đã tạo vị, như thế này một:

class IsSameX:public unary_function<CMyClass*, bool> 
{ 
    int num; 
public: 
    IsSameX(int n):num(n){} 
    bool operator()(CMyClass* obj) const 
    { 
     return (obj != NULL && (obj->X() == num)); 
    } 
}; 

Và kết thúc với một loạt các chức năng mà tất cả trông như thế này:

CMyClass* CMyVector::FindByX(int x) 
{ 
    CMyVector::iterator it = find_if(vec.begin(), vec.end(), IsSameX(x)); 
    if (it != vec.end()) 
    { 
     return *it; 
    } 
    return NULL; 
} 

Tất cả họ đều giống nhau, ngoại trừ các vị đó là gọi, vì vậy tôi đã nghĩ đến việc đơn giản hóa hơn, và tạo ra một chức năng như thế này:

CMyClass* CMyVector::Find(ThisIsWhatIDontKnow Predicate) 
{ 
    CMyVector::iterator it = find_if(vec.begin(), vec.end(), Predicate); 
    if (it != vec.end()) 
    { 
     return *it; 
    } 
    return NULL; 
} 

và làm:

CMyClass* CMyVector::FindByX(int x) 
{ 
    return Find(IsSameX(x)); 
} 

Và cứ tiếp tục như vậy.

Vì vậy, câu hỏi của tôi là: Làm cách nào để khai báo hàm Find của tôi để tôi có thể chuyển vị ngữ của tôi? Tôi đã thử một số cách, nhưng không có may mắn cho đến nay.

+0

Bạn có thể bọc mẫu tìm trong mẫu khác như được đề xuất hoặc sử dụng 'const std :: function &' làm tham số biến vị ngữ. – AJG85

Trả lời

10

sử dụng mẫu để mất trong bất cứ bao giờ gõ bạn cần

template<typename UnaryPredicate> 
CMyClass* CMyVector::Find(UnaryPredicate Predicate) 
{ 
    CMyVector::iterator it = find_if(vec.begin(), vec.end(), Predicate); 
    if (it != vec.end()) 
    { 
     return *it; 
    } 
    return NULL; 
} 

Bạn có thể nhất luôn cũng sử dụng std :: function (C++ 11)

CMyClass* CMyVector::Find(std::function<bool(const (CMYClass*)&)> Predicate) 
{ 
    CMyVector::iterator it = find_if(vec.begin(), vec.end(), Predicate); 
    if (it != vec.end()) 
    { 
     return *it; 
    } 
    return NULL; 
} 

Cá nhân tôi thích một đầu, bởi vì nó có thể sẽ dễ dàng hơn cho trình biên dịch để tối ưu hóa vì có ít sự gián tiếp hơn. và nếu cuộc gọi là duy nhất nó có thể nhận được inlined.

EDIT: Cũng đáng chú ý là nếu bạn đi với tùy chọn templated, bạn sẽ phải cung cấp việc thực hiện trong tập tin tiêu đề, điều này có thể là một nỗi đau. Trong khi đó, hàm std :: có thể nằm trong tệp nguồn (.cpp) với tất cả các triển khai khác.

+0

Cảm ơn, tôi chưa có C++ 11, vì vậy tôi sẽ phải đi theo cách mẫu. – MikMik

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