C++ std::设置用户定义的类型,如何确保没有重复
因此,我有一个std::set,它需要保持特定的顺序,并且不允许重复用户定义(由我定义)的类型。现在,我可以通过重载“C++ std::设置用户定义的类型,如何确保没有重复,c++,set,C++,Set,因此,我有一个std::set,它需要保持特定的顺序,并且不允许重复用户定义(由我定义)的类型。现在,我可以通过重载“操作符==未被std::set使用来获得正确工作的命令。元素a和b被视为等同于!(a
操作符==
未被std::set
使用来获得正确工作的命令。元素a
和b
被视为等同于!(a
运算符==
未被std::set
使用。元素a
和b
被视为等同于!(a
STL集实现在概念上做了类似的事情来检测相等性:
bool equal = !(a < b) && !(b < a);
bool equal=!(a
也就是说,如果两个元素都不小于另一个元素,那么它们必须相等。您可以通过在操作符==()
方法上设置断点并检查它是否被调用来检查这一点
我通常会怀疑检查完全不同事物的比较运算符。您的
STL集实现在概念上做了如下操作来检测相等性:
bool equal = !(a < b) && !(b < a);
bool equal=!(a
也就是说,如果两个元素都不小于另一个元素,那么它们必须相等。您可以通过在操作符==()
方法上设置断点并检查它是否被调用来检查这一点
我通常会怀疑检查完全不同事物的比较运算符。您的std::set
支持指定比较函数。默认值为less
,它将使用操作符std::set
支持指定比较函数。默认值为less
,它将使用操作符您可以尝试以下操作:
//! An element used in the route calculation.
struct RouteElem {
int shortestToHere; // Shortest distance from the start.
int heuristic; // The heuristic estimate to the goal.
Coordinate position;
bool operator<( const RouteElem& other ) const
{
return (heuristic+shortestToHere) < (other.heuristic+other.shortestToHere);
}
bool operator==( const RouteElem& other ) const
{
return (position.x == other.position.x && position.y == other.position.y);
}
};
struct CompareByPosition {
bool operator()(const RouteElem &lhs, const RouteElem &rhs) {
if (lhs.position.x != rhs.position.x)
return lhs.position.x < rhs.position.x;
return lhs.position.y < rhs.position.y;
}
};
// first, use std::set to remove duplicates
std::set<RouteElem,CompareByPosition> routeset;
// ... add each RouteElem to the set ...
// now copy the RouteElems into a vector
std::vector<RouteElem> routevec(routeset.begin(), routeset.end());
// now sort via operator<
std::sort(routevec.begin(), routevec.end());
尽管要注意,这并没有提供例外保证。如果第二次插入抛出,则routeset已被修改,因此状态不再一致。所以我想你真的需要:
if (routeset.insert(elem).second) {
try {
routemultiset.insert(elem); // I assume strong exception guarantee
} catch(...) {
routeset.erase(elem); // I assume nothrow. Maybe should check those.
throw;
}
}
或者与RAII等效,如果代码中只有一个地方使用过RAII类,那么RAII将更加详细,但如果重复次数较多,则会更好。您可以尝试以下方法:
//! An element used in the route calculation.
struct RouteElem {
int shortestToHere; // Shortest distance from the start.
int heuristic; // The heuristic estimate to the goal.
Coordinate position;
bool operator<( const RouteElem& other ) const
{
return (heuristic+shortestToHere) < (other.heuristic+other.shortestToHere);
}
bool operator==( const RouteElem& other ) const
{
return (position.x == other.position.x && position.y == other.position.y);
}
};
struct CompareByPosition {
bool operator()(const RouteElem &lhs, const RouteElem &rhs) {
if (lhs.position.x != rhs.position.x)
return lhs.position.x < rhs.position.x;
return lhs.position.y < rhs.position.y;
}
};
// first, use std::set to remove duplicates
std::set<RouteElem,CompareByPosition> routeset;
// ... add each RouteElem to the set ...
// now copy the RouteElems into a vector
std::vector<RouteElem> routevec(routeset.begin(), routeset.end());
// now sort via operator<
std::sort(routevec.begin(), routevec.end());
尽管要注意,这并没有提供例外保证。如果第二次插入抛出,则routeset已被修改,因此状态不再一致。所以我想你真的需要:
if (routeset.insert(elem).second) {
try {
routemultiset.insert(elem); // I assume strong exception guarantee
} catch(...) {
routeset.erase(elem); // I assume nothrow. Maybe should check those.
throw;
}
}
或者与RAII等价,如果代码中只有一个地方使用过RAII类,那么RAII将更加冗长,但是如果重复次数较多,则会更好。请注意这一点的后果。看起来您正在尝试执行类似于A*的操作,如果您尝试插入“重复”,它将被忽略,即使存在“更好”的路由
注意:此解决方案不起作用,请参见下面的逐一解释
struct RouteElem
{
int shortestToHere; // Shortest distance from the start.
int heuristic; // The heuristic estimate to the goal.
Coordinate position;
bool operator<( const RouteElem& other ) const
{
return (heuristic+shortestToHere) < (other.heuristic+other.shortestToHere);
}
bool operator==( const RouteElem& other ) const
{
return (position.x == other.position.x && position.y == other.position.y);
}
};
struct RouteElemLessThan : public std::binary_function<RouteElem, RouteElem, bool>
{
bool operator()(const RouteElem& lhs, const RouteElem& rhs) const
{
return !(lhs == rhs) && (lhs < rhs);
}
};
std::set<RouteElem, RouteElemLessThan> my_set;
struct RouteElem
{
int shortestToHere;//距起点的最短距离。
int启发式;//对目标的启发式估计。
坐标位置;
bool操作符请注意这一操作的后果。看起来您正在尝试执行类似于A*的操作,如果您尝试插入一个“副本”,它将被忽略,即使存在“更好”的路由
注意:此解决方案不起作用,请参见下面的逐一解释
struct RouteElem
{
int shortestToHere; // Shortest distance from the start.
int heuristic; // The heuristic estimate to the goal.
Coordinate position;
bool operator<( const RouteElem& other ) const
{
return (heuristic+shortestToHere) < (other.heuristic+other.shortestToHere);
}
bool operator==( const RouteElem& other ) const
{
return (position.x == other.position.x && position.y == other.position.y);
}
};
struct RouteElemLessThan : public std::binary_function<RouteElem, RouteElem, bool>
{
bool operator()(const RouteElem& lhs, const RouteElem& rhs) const
{
return !(lhs == rhs) && (lhs < rhs);
}
};
std::set<RouteElem, RouteElemLessThan> my_set;
struct RouteElem
{
int shortestToHere;//距起点的最短距离。
int启发式;//对目标的启发式估计。
坐标位置;
布尔运算符rlbond的比较器不阻止插入比较相等的元素。显然,鉴于字符限制,很难在注释中证明这一点,因为rlbond似乎认为std::set保证它不会包含两个!compare(a,b)&&&!compare(b,a)的元素
用于他的比较器。但是,rlbond的比较器没有定义严格的顺序,因此不是std::set的有效参数
#include <set>
#include <iostream>
#include <iterator>
#include <algorithm>
struct BrokenOrder {
int order;
int equality;
public:
BrokenOrder(int o, int e) : order(o), equality(e) {}
bool operator<(const BrokenOrder &rhs) const {
return order < rhs.order;
}
bool operator==(const BrokenOrder &rhs) const {
return equality == rhs.equality;
}
};
std::ostream &operator<<(std::ostream &stream, const BrokenOrder &b) {
return stream << b.equality;
}
// rlbond's magic comparator
struct LessThan : public std::binary_function<BrokenOrder, BrokenOrder, bool> {
bool operator()(const BrokenOrder& lhs, const BrokenOrder& rhs) const
{
return !(lhs == rhs) && (lhs < rhs);
}
};
int main() {
std::set<BrokenOrder,LessThan> s;
for (int i = 0; i < 5; ++i) {
s.insert(BrokenOrder(i,i));
}
for (int i = 0; i < 5; ++i) {
s.insert(BrokenOrder(10-i,i));
}
std::copy(s.begin(), s.end(),
std::ostream_iterator<BrokenOrder>(std::cout, "\n"));
}
重复项。magic comparator失败。集合中的不同元素具有相同的相等值
,因此将其与运算符==
进行比较,因为在插入过程中集合从未将新元素与其重复项进行比较。唯一排除的重复项是4,因为两个4具有排序顺序这使他们在一组中足够接近,可以相互比较
<> P>从C++标准:25.3:3“算法正确工作,COMP必须对值产生严格的弱排序”
25.3:4“……要求comp和equiv都是传递关系:
comp(a,b) && comp(b,c) implies comp(a,c)"
现在,考虑元素<代码> A= BROKEN命令(1,1)< /代码>,<代码> B= BROKEN命令(2,2)< /代码>,和<代码> C= BROKEONDENT(9,1)< /代码>,和<代码> COMP当然等于魔术比较器。
comp(a,b)
为真,因为1!=2(相等)和1<2(顺序)
comp(b,c)
是真的,因为2!=1(相等)和2<9(顺序)
comp(a,c)
为false,因为1==1(相等)
rlbond的比较器不会阻止插入比较相等的元素。鉴于字符限制,显然很难在注释中证明这一点,因为rlbond似乎认为std::set保证它不会包含两个!compare(a,b)&&&!compare(b,a)的元素
用于他的比较器。但是,rlbond的比较器没有定义严格的顺序,因此不是std::set的有效参数
#include <set>
#include <iostream>
#include <iterator>
#include <algorithm>
struct BrokenOrder {
int order;
int equality;
public:
BrokenOrder(int o, int e) : order(o), equality(e) {}
bool operator<(const BrokenOrder &rhs) const {
return order < rhs.order;
}
bool operator==(const BrokenOrder &rhs) const {
return equality == rhs.equality;
}
};
std::ostream &operator<<(std::ostream &stream, const BrokenOrder &b) {
return stream << b.equality;
}
// rlbond's magic comparator
struct LessThan : public std::binary_function<BrokenOrder, BrokenOrder, bool> {
bool operator()(const BrokenOrder& lhs, const BrokenOrder& rhs) const
{
return !(lhs == rhs) && (lhs < rhs);
}
};
int main() {
std::set<BrokenOrder,LessThan> s;
for (int i = 0; i < 5; ++i) {
s.insert(BrokenOrder(i,i));
}
for (int i = 0; i < 5; ++i) {
s.insert(BrokenOrder(10-i,i));
}
std::copy(s.begin(), s.end(),
std::ostream_iterator<BrokenOrder>(std::cout, "\n"));
}
重复项。magic comparator失败。集合中的不同元素具有相同的相等值
,因此将其与运算符==
进行比较,因为在插入过程中集合从未将新元素与其重复项进行比较。唯一排除的重复项是4,因为两个4具有排序