我有一个类ShapeDisplay
,它存储了一组Rectangle
。我想将它们排序存储,因此我使用std::set
。我的目的是提供一个自定义比较器,它将矩形的原点(x, y)与显示中的参考点(x, y)进行比较。
然而,为了实现这一点,比较器需要访问m_reference
。如何使用需要访问类成员的自定义比较器?我的设计有缺陷吗?我知道有更新的方法来提供比较器,如在这个链接中,但这并不能解决我的访问问题。
或者,我可以有一个std::vector
,我保持排序,这样每个新的Rectangle
被插入到正确的位置。但是,由于std::set::insert()
应该使用自定义比较器自动执行此操作,因此我更愿意这样做。
谢谢。
struct Point
{
int x;
int y;
};
struct Rectangle
{
int x;
int y;
int width;
int height;
};
class ShapeDisplay
{
void insertShape(Rectangle rect)
{
m_shapes.insert(rect);
}
void setReference(Point reference)
{
m_reference = reference;
}
private:
struct CenterComparator
{
bool operator() (const Rectangle & a, const Rectangle & b) const
{
double distA = std::sqrt(std::pow(a.x - m_reference.x, 2)
+ std::pow(a.y - m_reference.y, 2));
double distB = std::sqrt(std::pow(b.x - m_reference.x, 2)
+ std::pow(b.y - m_reference.y, 2));
return distA < distB;
}
};
std::set<Rectangle, CenterComparator> m_shapes;
Point m_reference;
};
CenterComparator
与ShapeDisplay
没有关系,它不知道其成员,也不是从ShapeDisplay
派生的。您需要为CenterComparator
提供它自己的引用Point
。然后,您需要提供一个CenterComparator
的实例,该实例的参考点已设置。
请注意,如果您以任何方式更改比较器的参考点,如果您尝试使用它,您将破坏std::set
的排序,从而导致未定义行为。因此,无论何时调用setReference
,您都需要使用新的比较器创建一个新集合,并复制旧集合。
下面是您的代码,经过了这些修改。我认为你的意思是setReference
和insertShape
是公共接口的一部分。
#include <cmath>
#include <set>
struct Point
{
int x;
int y;
};
struct Rectangle
{
int x;
int y;
int width;
int height;
};
class ShapeDisplay
{
public:
void insertShape(Rectangle rect)
{
m_shapes.insert(rect);
}
void setReference(Point reference)
{
m_reference = reference;
// Create a comparator using this new reference
auto comparator = CenterComparator{};
comparator.reference = m_reference;
// Create a new set
auto new_shapes = std::set<Rectangle, CenterComparator>(
std::begin(m_shapes), std::end(m_shapes), // Copy these shapes
comparator); // Use this comparator
m_shapes = std::move(new_shapes);
}
private:
struct CenterComparator
{
bool operator() (const Rectangle & a, const Rectangle & b) const
{
double distA = std::sqrt(std::pow(a.x - reference.x, 2)
+ std::pow(a.y - reference.y, 2));
double distB = std::sqrt(std::pow(b.x - reference.x, 2)
+ std::pow(b.y - reference.y, 2));
return distA < distB;
}
Point reference;
};
std::set<Rectangle, CenterComparator> m_shapes;
Point m_reference;
};