2017-10-08 12 views
6

Vì vậy, tôi đã nhìn vào sự hỗ trợ cho tra cứu không đồng nhất trong container liên kết của STL (kể từ C++ 14) và có một chút nhầm lẫn về những gì chúng ta có thể làm và những gì chúng ta không nên.
sau ĐoạnChúng tôi có thể sử dụng bộ so sánh tra cứu không đồng nhất để thực hiện tìm kiếm "một phần khớp" trên các vùng chứa liên kết STL không?

#include <algorithm> 
#include <iostream> 
#include <set> 

struct partial_compare : std::less<> 
{ 
    //"full" key_type comparison done by std::less 
    using less<>::operator(); 

    //"sequence-partitioning" comparison: only check pair's first member 
    bool operator()(std::pair<int, int> const &lhs, int rhs) const 
    { 
     return lhs.first < rhs; 
    } 

    bool operator()(int lhs, std::pair<int, int> const &rhs) const 
    { 
     return lhs < rhs.first; 
    } 
}; 

int main() 
{ 
    //Using std::set's lookup 
    { 
     std::cout << "std::set's equal_range:\n"; 
     std::set <std::pair<int, int>, partial_compare> s{{1,0},{1,1},{1,2},{1,3},{2,0}}; 

     auto r = s.equal_range (1); 

     for (auto it = r.first; it != r.second; ++it) 
     { 
      std::cout << it->first << ", " << it->second << '\n'; 
     } 

     std::cout << "std::set's lower_bound + iteration on equivalent keys:\n"; 
     auto lb = s.lower_bound(1); 

     while (lb != std::end(s) && !s.key_comp()(lb->first, 1) && !s.key_comp()(1, lb->first)) 
     { 
      std::cout << lb->first << ", " << lb->second << '\n'; 
      ++lb; 
     } 
    } 

    //Using algorithms on std::set 
    { 
     std::cout << "std::equal_range\n"; 
     std::set <std::pair<int, int>> s{{1,0},{1,1},{1,2},{1,3},{2,0}}; 

     auto r = std::equal_range (std::begin(s), std::end(s), 1, partial_compare{}); 
     for (auto it = r.first; it != r.second; ++it) 
     { 
      std::cout << it->first << ", " << it->second << '\n'; 
     } 
    } 
    return 0; 
} 

Tạo đầu ra sau khi biên dịch với kêu vang-5/libC++:

std::set's equal_range: 
1, 1 
std::set's lower_bound + iteration on equivalent keys: 
1, 0 
1, 1 
1, 2 
1, 3 
std::equal_range 
1, 0 
1, 1 
1, 2 
1, 3 

Và sau khi biên dịch với gcc-7.1.0:

std::set's equal_range: 
1, 0 
1, 1 
1, 2 
1, 3 
std::set's lower_bound + iteration on equivalent keys: 
1, 0 
1, 1 
1, 2 
1, 3 
std::equal_range 
1, 0 
1, 1 
1, 2 
1, 3 

Bằng cách đọc đề xuất ban đầu N3465, tôi nghĩ rằng những gì tôi đang làm ở đây sẽ ổn và khái niệm giống với những gì trong chuyên nghiệp ví dụ ban đầu của posal: một "match-match" trong quá trình tra cứu, dựa vào "khái niệm phân vùng trình tự".
Bây giờ, nếu tôi hiểu chính xác, những gì thực sự kết thúc trong tiêu chuẩn là N3657, nhưng điều đó dường như không thay đổi khái niệm vì nó "chỉ" tập trung vào việc đảm bảo mẫu thành viên tra cứu không đồng nhất chỉ có sẵn khi được cung cấp so sánh "is_transparent".
Vì vậy, tôi thực sự không thể hiểu tại sao sử dụng mẫu thành viên std :: set's equal_range trong clang/libC++ không tạo ra kết quả tương tự của gcc hoặc tương đương "lower_bound + scan". Tôi thiếu một cái gì đó và sử dụng tra cứu không đồng nhất theo cách này thực sự vi phạm tiêu chuẩn (và sau đó kêu vang là đúng và sự khác biệt giữa equal_rangelower_bound + quét có thể do UB), hoặc là clang/libC++ sai?

EDIT: Sau khi đọc câu trả lời được chấp nhận ngay bây giờ, tôi có thể tìm thấy bug report có liên quan cho libC++.
Ngoài ra còn có một câu hỏi cụ thể về sự khác biệt trong hành vi của equal_range thành viên mẫu giữa libC++ và libstdC++ here trên SO mà tôi không tìm thấy khi thực hiện tìm kiếm của mình.
Không chắc chắn nếu điều này sẽ bị xóa hoặc đóng, vì tài khoản tôi đã liên kết không có câu trả lời được chấp nhận.

+0

Thay đổi thành 'upper_bound' sẽ sạch hơn nhiều. – o11c

+0

@ o11c đúng, nhưng vì nghi ngờ về những gì clang đang làm, tôi thích sử dụng một phương pháp "thủ công" hoàn toàn để giảm khả năng bị cắn bởi cùng một vấn đề có thể ảnh hưởng đến equal_range. – abigagli

Trả lời

6

Đây là lỗi trong libC++: equal_range implementation (tại r315179) ngay lập tức trả về cả hai trình lặp khi tìm kiếm phần tử "bằng nhau" ngay cả khi so sánh không đồng nhất.

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