需要访问其他成员变量的std::set类型成员变量的比较器



我有一个类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;
};

CenterComparatorShapeDisplay没有关系,它不知道其成员,也不是从ShapeDisplay派生的。您需要为CenterComparator提供它自己的引用Point。然后,您需要提供一个CenterComparator的实例,该实例的参考点已设置。

请注意,如果您以任何方式更改比较器的参考点,如果您尝试使用它,您将破坏std::set的排序,从而导致未定义行为。因此,无论何时调用setReference,您都需要使用新的比较器创建一个新集合,并复制旧集合。

下面是您的代码,经过了这些修改。我认为你的意思是setReferenceinsertShape是公共接口的一部分。

#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;
};

最新更新