2015-05-26 21 views
6

Nhiệm vụ thường xuyên của tôi là viết tất cả toán tử so sánh quá tải cho một lớp, vì vậy tôi đã viết một lớp mẫu thực hiện <, < =,> =,! = Nếu lớp dẫn xuất thực hiện == và <. Nó đang làm việc nhưng tính năng rất nhiều diễn viên và không rõ ràng là "mẫu kỳ lạ mẫu định kỳ", vì vậy tôi tự hỏi, nếu có những giải pháp đơn giản?Lớp mẫu thực hiện toán tử so sánh

template <class Derived> 
class Comparable 
{ 
public: 

    bool operator!=(const Comparable<Derived>& other) { 
     return !(static_cast<Derived*>(this)->operator== 
        (*static_cast<const Derived*>(&other))); 
    } 

    bool operator<=(const Comparable<Derived>& other) { 
     return (static_cast<Derived*>(this)->operator== 
        (*static_cast<const Derived*>(&other))) 
       || (static_cast<Derived*>(this)->operator< 
        (*static_cast<const Derived*>(&other))); 
    } 

    bool operator>(const Comparable<Derived>& other) { 
     return !(static_cast<Derived*>(this)->operator== 
        (*static_cast<const Derived*>(&other))) 
       && !(static_cast<Derived*>(this)->operator< 
        (*static_cast<const Derived*>(&other))); 
    } 

    bool operator>=(const Comparable<Derived>& other) { 
     return !(static_cast<Derived*>(this)->operator< 
        (*static_cast<const Derived*>(&other))); 
    } 
}; 
+3

http://www.boost.org/doc/libs/1_58_0/libs/utility/operators.htm – interjay

+0

Có. Tôi đã đề xuất một giải pháp tương tự cho những gì @interjay liên kết ở trên: định nghĩa hàm friend bên trong một lớp là * inline * d các hàm miễn phí có thể được tìm thấy thông qua ADL trên kiểu có nguồn gốc. Bạn có thể sử dụng nó để cung cấp cho các toán tử bạn cần. –

Trả lời

4

Trong trường hợp nó không phải là rõ ràng từ mô tả trong các bình luận:

template <typename T> 
struct Comparable { 
    friend bool operator!=(T const & lhs, T const & rhs) { return !(lhs == rhs); } 
    friend bool operator> (T const & lhs, T const & rhs) { return rhs < lhs; } 
// ... 
}; 
class MyType : Comparable<MyType> { 
    int data; 
    friend bool operator==(MyType const & lhs, MyType const & rhs) { 
     return lhs.data == rhs.data; 
    } 
    friend bool operator< (MyType const & lhs, MyType const & rhs) { 
     return lhs.data < rhs.data; 
    } 
    public: 
// ... 
}; 

Khi trình biên dịch gặp MyType a, b; a > b; tra cứu cho các nhà điều hành sẽ kết thúc làm ADL sẽ nhìn vào bên trong MyTypeComparable<MyType> (như đây là một cơ sở), nơi nó sẽ tìm thấy việc thực hiện bạn cần: bool operator>(MyType const&, MyType const&).

Các toán tử là hàm tự do cho phép định nghĩa nằm ngoài kiểu được so sánh (trong trường hợp này là cơ sở), trong khi làm cho các toán tử đó chỉ có sẵn thông qua ADL (một trong hai đối số phải là Comparable<MyType>). Việc sử dụng chức năng miễn phí cũng cung cấp tính đối xứng kiểu, trình biên dịch sẽ cho phép chuyển đổi ngầm ở cả hai bên, trong trường hợp chức năng thành viên, nó sẽ chỉ cho phép chuyển đổi ở phía bên tay phải của toán tử.


Để hoàn chỉnh, một thủ thuật khác nhau có thể được thực hiện là cung cấp cho các nhà khai thác như các mẫu trong một không gian tên cùng với một thẻ có thể được sử dụng để mang lại không gian tên rằng trong cho các mục đích ADL:

namespace operators { 
    template <typename T> 
    bool operator>(T const & lhs, T const & rhs) { 
     return rhs < lhs;  
    } 
// rest of the operators come here 
    struct tag {}; 
} 
class MyType : operators::tag { 
    int data; 
    friend bool operator<(T const & lhs, T const & rhs) { 
     return lhs.data < rhs.data; 
    } 
//... 
}; 

Bí quyết về cơ bản là giống nhau, ngoại trừ trong trường hợp này các toán tử không được tìm thấy bên trong cơ sở, nhưng trong một không gian tên được liên kết với nó. Giải pháp này hơi tốt hơn một chút so với giải pháp trước, vì nó được mở cho các hình thức lạm dụng khác nhau, bao gồm using namespace operators; sẽ làm cho các toán tử có sẵn cho tất cả các loại.

+0

Tôi nghĩ rằng điều này sẽ không hiệu quả do không thể vượt qua tình bạn. – simon

+0

@ simon: Điều này không liên quan gì tới tình bạn, từ khóa 'friend' được sử dụng để cho phép định nghĩa hàm tự do bên trong định nghĩa lớp, nhưng việc triển khai chỉ sử dụng giao diện công khai. –

+0

Vâng, tôi hiểu, cảm ơn. – simon

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