2013-05-02 36 views
11

Tôi muốn tạo loại hỗn hợp ra khỏi hai số enum classes.Tạo loại hỗn hợp từ hai lớp enum, sẵn sàng cho bản đồ STL

enum class Color {RED, GREEN, BLUE}; 
enum class Shape {SQUARE, CIRCLE, TRIANGLE}; 

class Object { 
    Color color; 
    Shape shape; 
public: 
}; 

Để sử dụng Object trong một container STL như std::map<> tôi sẽ cần phải quá tải ít hơn điều hành. Tuy nhiên, để san bằng cả hai lớp enum vào một chỉ số tuyến tính tôi bằng cách nào đó cần số phần tử (Noé) của các lớp enum:

friend bool operator< (const Object &lhs, const Object &rhs) { 
    return NoE(Shape)*lhs.color+lhs.shape < NoE(Shape)*rhs.color+rhs.shape; 
} 

Làm thế nào điều này có thể được thực hiện mà không cần nhập các thông tin tương tự (số phần tử) ở hai nơi trong chương trình một cách tốt đẹp? (Cách tốt đẹp nghĩa là không có FIRST_ELEMENT, LAST_ELEMENT, ma thuật tiền xử lý, v.v.)

Câu hỏi (Number of elements in an enum) tương tự nhưng không địa chỉ enum classes.

Tôi muốn biết cách tốt nhất để triển khai loại kết hợp này trong C++ 11 là gì. Là định nghĩa lớp enum đủ mạnh, hoặc là nó cần thiết để nói :?

enum class Color {RED=0, GREEN=1, BLUE=2}; 
enum class Shape {SQUARE=0, CIRCLE=1, TRIANGLE=2}; 
+0

Theo như tôi biết tình huống 'enum' đã không thay đổi trong C++ 11. – syam

+0

Tại sao bạn cần làm phẳng? Đó không phải là một yêu cầu cho 'std :: map', mà chỉ đơn giản đòi hỏi thứ tự yếu nghiêm ngặt. Bạn có thể dễ dàng làm điều đó với một số so sánh lồng nhau. – Chad

+0

'toán tử <' chỉ được yêu cầu nếu nó là khóa trong 'map', không phải nếu nó là giá trị. Giả sử nó là chìa khóa, tại sao không ưu tiên 'Color' hoặc' Shape' trong bộ so sánh? Nó không kém ý nghĩa hơn so với toán tử 'đã đăng <. – hmjd

Trả lời

15

Như nhận xét và như đã đề cập bởi những người khác, dành ưu tiên cho một trong hai Shape hoặc Color trong operator< và chỉ so sánh khác, nếu là người đầu tiên là công bằng. An thực hiện thay thế cho operator< sử dụng std::tie:

#include <tuple> 
friend bool operator<(const Object& lhs, const Object& rhs) 
{ 
    return std::tie(lhs.color, lhs.shape) < std::tie(rhs.color, rhs.shape); 
} 
+0

+1. Tôi vừa mới viết câu trả lời này! – juanchopanza

2

Đó là một câu hỏi hay, nhưng bạn không thực sự cần số lượng Color để so sánh chúng:

friend bool operator< (const Object &lhs, const Object &rhs) { 
    if(lhs.color > rhs.color) { 
     return false; 
    } 
    if(lhs.color < rhs.color) { 
     return true; 
    } 
    return lhs.shape < rhs.shape; 
} 
4

Bạn không cần phải có chỉ số tuyến tính, bạn chỉ có thể so sánh chúng lexicographically:

friend bool operator< (const Object &lhs, const Object &rhs) { 
    if (lhs.color < rhs.color) return true; 
    else if (lhs.color > rhs.color) return false; 
    else return lhs.shape < rhs.shape; 
} 
2

Điều bạn đang cố gắng thể hiện là để xác định thứ tự các đối tượng của bạn, trước tiên bạn cần so sánh màu sắc, và sau đó kiểm tra hình dạng trong trường hợp màu sắc là như nhau. Thay vì linearizing rằng, nếu chỉ đơn giản là sẽ sử dụng các toán tử boolean.

friend bool operator< (const Object &lhs, const Object &rhs) 
{ 
    return ((lhs.color < rhs.color) 
      || ((lhs.color == rhs.color) && (lhs.shape < rhs.color))) 
} 

EDIT: Thực ra, bạn cũng có thể sử dụng một trên ràng buộc về số lượng các đối tượng, hành vi sẽ giống nhau:

friend bool operator< (const Object &lhs, const Object &rhs) { 
    return 10000*lhs.color+lhs.shape < 10000*rhs.color+rhs.shape; 
} 

nhưng đó giới thiệu một "con số kỳ diệu" (vì vậy không như vậy một ý tưởng hay).

2

Bạn chỉ cần so sánh shape nếu color giống nhau cho cả hai.

Sử dụng một ternary bạn có thể làm cho nó trông đẹp quá:

friend bool operator< (const Object &lhs, const Object &rhs) { 
    return lhs.color == rhs.color ? (lhs.shape < rhs.shape) 
            : (lhs.color < rhs.color); 
} 
7

Xem xét sử dụng đơn giản std::tuple<Color, Shape> là "enum composite." Điều này sẽ đi kèm với các toán tử so sánh đã được xác định cho bạn, sử dụng một thứ tự từ điển.Ví dụ: mã hợp lệ:

bool b = std::make_tuple(Color::RED, Shape::CIRCLE) 
     < std::make_tuple(Color::GREEN, Shape::SQUARE); 
Các vấn đề liên quan