需要访问其他成员变量的 std::set 类型成员变量的比较器
Comparator for member variable of type std::set that requires access to other member variables
我有一个 class ShapeDisplay
存储一组 Rectangle
。我想按顺序存储它们,因此我使用 std::set
。我的目的是提供一个自定义比较器,它将矩形的原点 (x, y) 与显示中的参考点 (x, y) 进行比较。
然而,为了实现这一点,比较器需要访问 m_reference
。如何使用需要访问 class 成员的自定义比较器?我的设计有缺陷吗?我知道有更新的方法可以将比较器作为 in this link, 提供,但这并不能解决我的访问问题。
或者,我可以只对 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
是 public 接口的一部分。
#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;
};
我有一个 class ShapeDisplay
存储一组 Rectangle
。我想按顺序存储它们,因此我使用 std::set
。我的目的是提供一个自定义比较器,它将矩形的原点 (x, y) 与显示中的参考点 (x, y) 进行比较。
然而,为了实现这一点,比较器需要访问 m_reference
。如何使用需要访问 class 成员的自定义比较器?我的设计有缺陷吗?我知道有更新的方法可以将比较器作为 in this link, 提供,但这并不能解决我的访问问题。
或者,我可以只对 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
是 public 接口的一部分。
#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;
};