11

我想从两个中创建一个复合类型enum classes

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

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

为了Object在 STL 容器中使用,std::map<>我需要重载小于运算符。但是,为了将两个枚举类扁平化为一个线性索引,我不知何故需要枚举类的元素数(NoE):

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

如果不以一种很好的方式在程序的两个位置输入相同的信息(元素数量),如何做到这一点?(好方法意味着不FIRST_ELEMENT, LAST_ELEMENT,预处理器魔术等)

问题(枚举中的元素数)类似但未解决enum classes

我想知道在 C++11 中实现这种复合类型的最佳方法是什么。枚举类定义是否足够强大,还是有必要说:?

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

6 回答 6

15

正如其他人所评论和已经陈述的那样,优先考虑其中一个ShapeColor中的一个,operator<并且仅在第一个相等时才比较另一个。operator<使用的替代实现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);
}
于 2013-05-02T14:43:11.893 回答
7

考虑简单地std::tuple<Color, Shape>用作“复合枚举”。这将附带已经为您定义的比较运算符,使用字典排序。例如,有效代码:

bool b = std::make_tuple(Color::RED, Shape::CIRCLE)
       < std::make_tuple(Color::GREEN, Shape::SQUARE);
于 2013-05-02T14:53:54.040 回答
4

您不需要线性索引,您可以简单地按字典顺序比较它们:

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;
}
于 2013-05-02T14:33:36.987 回答
2

这是一个很好的问题,但您实际上并不需要Color比较它们的数量:

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;
}
于 2013-05-02T14:33:24.187 回答
2

您要表达的是,要确定对象的顺序,首先需要比较颜色,然后检查形状以防颜色相同。if 不会将其线性化,而是简单地使用布尔运算符。

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

编辑:实际上,您也可以使用对象数量的上限,行为将是相同的:

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

但这引入了一个“幻数”(所以不是一个好主意)。

于 2013-05-02T14:33:54.503 回答
2

您只需要比较两者shape是否color相同。

使用三元组也可以让它看起来不错:

friend bool operator< (const Object &lhs, const Object &rhs) {
     return lhs.color == rhs.color ? (lhs.shape < rhs.shape)
                                   : (lhs.color < rhs.color);
}
于 2013-05-02T14:36:41.563 回答