2010-04-16 41 views
6

Tôi đang bối rối về giao diện của std::find. Tại sao nó không lấy một đối tượng Compare cho biết cách so sánh hai đối tượng?Làm thế nào để std :: tìm kiếm bằng cách sử dụng một đối tượng So sánh?

Nếu tôi có thể vượt qua một đối tượng Compare tôi có thể làm cho công việc mã sau đây, nơi tôi muốn so sánh theo giá trị, thay vì chỉ so sánh các giá trị con trỏ trực tiếp:

typedef std::vector<std::string*> Vec; 
Vec vec; 
std::string* s1 = new std::string("foo"); 
std::string* s2 = new std::string("foo"); 
vec.push_back(s1); 
Vec::const_iterator found = std::find(vec.begin(), vec.end(), s2); 
// not found, obviously, because I can't tell it to compare by value 
delete s1; 
delete s2; 

là sau cách khuyến khích để làm điều đó?

template<class T> 
struct MyEqualsByVal { 
    const T& x_; 
    MyEqualsByVal(const T& x) : x_(x) {} 
    bool operator()(const T& y) const { 
    return *x_ == *y; 
    } 
}; 
// ... 
vec.push_back(s1); 
Vec::const_iterator found = 
    std::find_if(vec.begin(), vec.end(), 
       MyEqualsByVal<std::string*>(s2)); // OK, will find "foo" 

Trả lời

6

find không thể quá tải để có một vị từ đơn nhất thay vì giá trị, vì đó là tham số mẫu không bị giới hạn. Vì vậy, nếu bạn gọi là find(first, last, my_predicate), sẽ có sự mơ hồ tiềm năng cho dù bạn muốn biến vị ngữ được đánh giá trên từng thành viên của dải ô hoặc liệu bạn có muốn tìm một thành viên của dải ô đó bằng chính biến vị ngữ hay không (đó có thể là phạm vi của các biến vị ngữ, cho tất cả các nhà thiết kế của các thư viện chuẩn biết hoặc quan tâm, hoặc value_type của trình lặp có thể được chuyển đổi cả về kiểu vị từ và đến argument_type). Do đó sự cần thiết cho find_if để đi theo một tên riêng biệt.

find có thể đã bị quá tải để có một vị từ nhị phân tùy chọn, ngoài giá trị được tìm kiếm. Nhưng nắm bắt các giá trị trong các hàm, như bạn đã làm, là một kỹ thuật tiêu chuẩn mà tôi không nghĩ rằng nó sẽ là một lợi ích lớn: nó chắc chắn không bao giờ cần thiết vì bạn luôn có thể đạt được kết quả tương tự với find_if.

Nếu bạn có số find bạn muốn, bạn vẫn phải viết một hàm (hoặc sử dụng tăng), vì <functional> không chứa bất kỳ thứ gì để coi trọng con trỏ. Tuy nhiên, hàm functor của bạn sẽ đơn giản hơn một chút như là một vị từ nhị phân, hoặc bạn có thể sử dụng một con trỏ hàm, vì vậy nó sẽ là một mức tăng khiêm tốn. Vì vậy, tôi không biết tại sao điều này không được cung cấp. Với số copy_if fiasco Tôi không chắc chắn có nhiều giá trị trong giả định luôn có lý do chính đáng cho các thuật toán không có sẵn :-)

+0

Cảm ơn! Trong tò mò, có gì sai với 'copy_if'? – Frank

+1

@dehmann: Điều duy nhất sai với nó là nó không có trong tiêu chuẩn. Nó bị bỏ lại chủ yếu do một tai nạn chỉnh sửa. –

2

là con trỏ, bạn cũng có thể lưu trữ bản sao con trỏ trong đối tượng hàm.

Ngoài ra, đó là cách nó được thực hiện và không có nhiều hơn cả với nó. Ngoài ra, nó không phải là một ý tưởng tốt để lưu trữ con trỏ trần trong một container, trừ khi bạn đang cực kỳ cẩn thận với việc đảm bảo an toàn ngoại lệ, đó là hầu như luôn luôn rắc rối hơn nó có giá trị.

+0

Và ... Tôi hoàn toàn bỏ lỡ nửa đầu câu hỏi ... oops. Mặc dù, câu trả lời của Steve Jessop tốt hơn tôi có thể giải thích được. –

0

Đó chính xác là những gì find_if dành cho - phải mất một vị từ được gọi để so sánh các phần tử.

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