Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ std::设置用户定义的类型,如何确保没有重复_C++_Set - Fatal编程技术网

C++ std::设置用户定义的类型,如何确保没有重复

C++ std::设置用户定义的类型,如何确保没有重复,c++,set,C++,Set,因此,我有一个std::set,它需要保持特定的顺序,并且不允许重复用户定义(由我定义)的类型。现在,我可以通过重载“操作符==未被std::set使用来获得正确工作的命令。元素a和b被视为等同于!(a

因此,我有一个std::set,它需要保持特定的顺序,并且不允许重复用户定义(由我定义)的类型。现在,我可以通过重载“
操作符==
未被
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具有排序