2012-11-13 26 views
16

Với một trình vòng lặp, có thể truy xuất/sử dụng hàm so sánh chính xác cho bộ sưu tập mà trình lặp này đề cập đến không?Truy xuất chức năng so sánh của thùng chứa với một trình lặp vòng

Ví dụ, chúng ta hãy giả sử tôi đang viết một thuật toán tổng quát:

template <class InIt, class T> 
void do_something(InIt b, InIt e, T v) { 
    // ... 
} 

Bây giờ, chúng ta hãy nói rằng tôi muốn làm điều gì đó đơn giản, giống như tìm v trong [b..e). Nếu be là trình lặp trên một số std::vector, tôi có thể chỉ cần sử dụng if (*b == v) .... Tuy nhiên, giả sử rằng be là các trình lặp qua một số std::map. Trong trường hợp này, tôi nên chỉ so sánh các phím , không phải toàn bộ loại giá trị của những gì có trong bản đồ.

Vì vậy, câu hỏi đặt ra là, khi đưa các vòng lặp đó vào bản đồ, làm cách nào để truy xuất hàm so sánh của bản đồ đó sẽ chỉ so sánh các khóa? Đồng thời, tôi cũng không muốn một cách mù quáng giả định rằng tôi đang làm việc với một số map. Ví dụ: nếu các trình vòng lặp trỏ đến một số set, tôi muốn sử dụng hàm so sánh được xác định cho rằng set. Nếu họ chỉ đến một số vector hoặc deque, tôi có thể phải sử dụng ==, vì các vùng chứa đó sẽ không có hàm so sánh được xác định. Ồ, gần như quên mất: Tôi nhận ra rằng trong nhiều trường hợp, một thùng chứa sẽ chỉ tương đương với operator< thay vì operator== cho các thành phần chứa trong đó - Tôi hoàn toàn ổn khi có thể sử dụng nó.

+0

Không có thời gian để viết câu trả lời ngay bây giờ, nhưng điều này có thể giúp http://en.cppreference.com/w/cpp/container/map/key_comp. Hmm, không nhiều, mặc dù. Phần khó khăn là nhận được các container. –

+0

Tôi đang nhầm lẫn với trường hợp 'set' của bạn. Bộ so sánh của một 'bộ' cần phải là tổng số thứ tự, không phải là trường hợp của' toán tử == '. – pmr

+0

Không giống nhau, cho dù bạn chỉ so sánh khóa của mục nhập bản đồ hoặc toàn bộ mục nhập? [Chỉnh sửa] Không bao giờ bận tâm, tất nhiên nó không phải là - bạn có thể không có một hoạt động bình đẳng trên một phần bản đồ. –

Trả lời

6

Không có cách tiêu chuẩn nào để ánh xạ từ trình lặp đến loại vùng chứa cơ bản (nếu có). Bạn có thể sử dụng một số chẩn đoán để cố gắng xác định vùng chứa nào, mặc dù điều đó sẽ không đơn giản và có thể không được đảm bảo.

Ví dụ, bạn có thể sử dụng một metafunction để xác định xem * value_type * là std::pair<const K, T>, mà là một gợi ý rằng đây có thể là một std::map và sau khi giải nén các loại KT cố gắng sử dụng một metafunction để xác định xem loại của trình lặp và loại đối sánh std::map<K,T,X,Y>::iterator hoặc std::map<K,T,X,Y>::const_iterator cho kết hợp cụ thể của X, Y.

Trong trường hợp bản đồ có thể đủ để xác định (tức là phỏng đoán có cơ hội thành công cao) mà trình lặp tham chiếu đến std::map, nhưng bạn nên lưu ý rằng ngay cả khi bạn có thể sử dụng và thậm chí trích xuất loại X của bộ so sánh, không đủ để sao chép bộ so sánh trong trường hợp chung. Trong khi các bộ so sánh không phổ biến (và không được khuyến nghị) có thể có trạng thái, và bạn sẽ không biết trạng thái cụ thể của bộ so sánh mà không có quyền truy cập trực tiếp vào vùng chứa.Cũng lưu ý rằng có những trường hợp kiểu heuristic này thậm chí sẽ không giúp ích, trong một số kiểu thực thi std::vector<> loại trình vòng lặp trực tiếp là một con trỏ, và trong trường hợp đó bạn không thể phân biệt giữa 'trình lặp' thành một mảng và một biến lặp thành một std::vector<> các loại cơ bản giống nhau.

11

Bộ lặp không nhất thiết phải kết nối với các thùng chứa, vì vậy chúng không cung cấp cho bạn bất kỳ chi tiết nào về các thùng chứa mà chúng không nhất thiết phải kết nối với. Đó là sự trừu tượng của trình vòng lặp thiết yếu: các trình vòng lặp phân định các chuỗi, mà không quan tâm đến trình tự xuất phát từ đâu. Nếu bạn cần biết về các thùng chứa, bạn phải viết các thuật toán lấy container.

+2

Ví dụ: một số 'chuỗi' và' vectơ' có các trình vòng lặp được triển khai dưới dạng con trỏ trần (tận dụng bộ đệm ẩn liên tiếp và tiếp giáp). –

+0

Thậm chí nếu bạn lấy các thùng chứa làm đối số, bạn vẫn cần phải dựa vào các thủ thuật để phân biệt một 'Chuỗi ký tự' từ một' AssociativeContainer'. Tôi cho rằng thật khó để viết một 'is_associative_container' hoạt động đáng tin cậy. – pmr

+0

@pmr: Đặc điểm đó thực sự đơn giản nếu bạn chỉ muốn hỗ trợ các thùng chứa chuẩn ... bạn chỉ cần xác định xem loại đó là một trong 'std :: map',' std :: multimap', 'std :: set hay không ',' std :: multiset' (và các phiên bản không có thứ tự nếu bạn cần hỗ trợ chúng, mặc dù khái niệm * comparator * không rõ ràng ở đó) –

3

Thật không may các trình vòng lặp không phải lúc nào cũng biết về vùng chứa chứa chúng (và đôi khi chúng không nằm trong một thùng chứa chuẩn). Ngay cả các iterator_traits chỉ có thông tin về value_type mà không cụ thể cho bạn biết làm thế nào để so sánh.

Thay vào đó, hãy lấy cảm hứng từ thư viện chuẩn. Tất cả các hộp chứa liên kết (map, v.v.) có các phương thức find riêng của chúng thay vì sử dụng std::find. Và nếu bạn do cần sử dụng std::find trên một vùng chứa như vậy, bạn không: bạn sử dụng find_if.

Có vẻ như giải pháp của bạn là đối với các thùng chứa liên kết, bạn cần một số do_something_if chấp nhận vị từ cho biết cách so sánh các mục nhập.

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