2015-02-01 29 views
7

với C++ 14, chúng tôi được phép so sánh các phần tử của một số vùng chứa liên kết (như std :: set) với các loại khác so với các phần tử được lưu trữ trong vùng chứa. Đó là nghĩa vụ phải làm việc khi so sánh có is_transparent được biểu thị dưới dạng một loại (xem ví dụ: std::set::find).Làm cách nào để sử dụng bộ so sánh với loại is_transparent?

Giả sử tôi có một wrapper chuỗi mà thực hiện một số kiểm tra trên một chuỗi (nếu đó là định dạng là định dạng hợp lệ và vân vân - không thực sự quan trọng, nhưng xây dựng nó là đủ nặng mà tôi muốn tránh nó + nó có thể ném ngoại lệ) và nó được lưu trữ trong std :: được thiết lập để có một vùng chứa các giá trị duy nhất. Làm thế nào tôi nên viết một so sánh cho nó? Nếu nó trông giống như dưới đây? Tôi có thể quá tải và sử dụng sw::operator<() để đạt được điều tương tự không?

class sw 
{ 
public: 
    explicit sw(const std::string& s) : s_(s) { /* dragons be here */ } 
    const std::string& getString() const { return s_; } 

    bool operator<(const sw& other) const { return s_ < other.s_; } 

private: 
    std::string s_; 
}; 

struct Comparator 
{ 
    using is_transparent = std::true_type; 

    bool operator()(const sw& lhs, const std::string& rhs) const { return lhs.getString() < rhs; } 
    bool operator()(const std::string& lhs, const sw& rhs) const { return lhs < rhs.getString(); } 
    bool operator()(const sw& lhs, const sw& rhs) const { return lhs < rhs; } 
}; 

int main() 
{ 
    std::set<sw, Comparator> swSet{ sw{"A"}, sw{"B"}, sw{"C"} }; 
    std::cout << std::boolalpha << (swSet.find(std::string("A")) != swSet.end()) << std::endl; 
} 

Tôi tin rằng mã trên nên làm việc như mong đợi, nhưng khi tôi thử nghiệm nó với g ++ 4.9 và kêu vang ++ 3.6, cả hai mang lại các lỗi về việc thiếu chuyển đổi string-key_type như nếu chuỗi quá tải của Comparator::operator() là không bao giờ được tính đến. Tui bỏ lỡ điều gì vậy?

+4

Các phiên bản của libstdC++ (thư viện chuẩn của gcc) đi kèm với g ++ 4.9 đã không thực hiện tra cứu không đồng nhất. Mã của bạn [biên dịch tốt với clang và libC++] (http://coliru.stacked-crooked.com/a/97c0421099d7912d). –

+0

@ T.C .: cảm ơn, điều đó có ý nghĩa và đó là những gì tôi đã sợ ... Tôi đã thử nó với clang và -stdlib = libC++ và nó hoạt động như dự định. Quá xấu mà môi trường mặc định của tôi là g ++ và libstdC++. –

+4

Nó được triển khai trong https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=219888, chưa đầy hai tuần trước. –

Trả lời

3

Vâng, mã số đó là đúng, nhưng nó sẽ đơn giản hơn để quá tải operator< để cho phép so sánh kiểu của bạn với std::string và sau đó chỉ cần sử dụng std::less<> (ví dụ: std::less<void>) đó là "minh bạch" rồi.

inline bool operator<(const sw& lhs, const std::string& rhs) { return lhs.getString() < rhs; } 
inline bool operator<(const std::string& lhs, const sw& rhs) { return lhs < rhs.getString(); } 

std::set<sw, std::less<>> swSet{ sw{"A"}, sw{"B"}, sw{"C"} }; 

Ngoài ra, nó có thể là đáng chú ý là nó không quan trọng những gì bạn xác định is_transparent tới, một trong những sẽ có tác dụng tương tự như định nghĩa của bạn của nó:

using is_transparent = std::false_type; 

using is_transparent = void; 
+0

Huh, tôi không biết về 'ít hơn ' và hành vi của nó, điều đó thật tuyệt. Tuy nhiên, khi làm những việc như vậy, tôi tìm thấy một trình so sánh riêng biệt và rõ ràng hơn, nhưng đó có lẽ là một sở thích cá nhân. :) –

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