尝试将 std::pair 插入到 std::set 中

5
我不明白这段代码中的错误在哪里:
```html

我无法理解此代码中的错误:

```
#include <set>
#include <utility>
#include <iostream>

using namespace std;

class A
{
    public:
        A(unsigned int a) : _a(a) { }
        A() : _a(0) { }
        unsigned int a() const { return _a; }
    private:
        unsigned int _a;
};

class B
{
    public:
        B(unsigned int b) : _b(b) { }
        B() : _b(0) { }
        unsigned int b() const { return _b; }
    private:
        unsigned int _b;
};

void display(const Point& point)
{
    //cout << "A: " << point.first.a() << ", B: " << point.second.b() << endl;
}

typedef pair <A, B> Point;
typedef set <Point> List;

main()
{
    A a(5);
    B b(9);

    List list;
    List::iterator it;
    Point point;

    point = make_pair(a, b);

    it = list.begin();

    list.insert(point); // <--- error here

    //display(point);
}

错误信息如下:

In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4/include/g++-v4/bits/stl_algobase.h:66,
                 from /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4/include/g++-v4/bits/stl_tree.h:62,
                 from /usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4/include/g++-v4/set:60,
                 from test.cpp:1:
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4/include/g++-v4/bits/stl_pair.h: In function ‘bool std::operator<(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&) [with _T1 = A, _T2 = B]’:
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4/include/g++-v4/bits/stl_function.h:230:   instantiated from ‘bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = std::pair<A, B>]’
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4/include/g++-v4/bits/stl_tree.h:1170:   instantiated from ‘std::pair<typename std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(const _Val&) [with _Key = std::pair<A, B>, _Val = std::pair<A, B>, _KeyOfValue = std::_Identity<std::pair<A, B> >, _Compare = std::less<std::pair<A, B> >, _Alloc = std::allocator<std::pair<A, B> >]’
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4/include/g++-v4/bits/stl_set.h:411:   instantiated from ‘std::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename _Alloc::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(const _Key&) [with _Key = std::pair<A, B>, _Compare = std::less<std::pair<A, B> >, _Alloc = std::allocator<std::pair<A, B> >]’
test.cpp:48:   instantiated from here
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4/include/g++-v4/bits/stl_pair.h:154: error: no match foroperator<’ in ‘__x->std::pair<A, B>::second < __y->std::pair<A, B>::second’
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4/include/g++-v4/bits/stl_pair.h:154: error: no match foroperator<’ in ‘__y->std::pair<A, B>::first < __x->std::pair<A, B>::first’
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.4/include/g++-v4/bits/stl_pair.h:154: error: no match foroperator<’ in ‘__x->std::pair<A, B>::first < __y->std::pair<A, B>::first’

4
如果你想使用std::set容器来存储类AB,或者是std::pair<A,B>,那么你的类必须实现LessThanComparable接口:http://www.sgi.com/tech/stl/LessThanComparable.html 。这是因为set被实现成红黑树,需要满足元素有序。 - phooji
@phooji:你应该把那个发表为答案。 - Bill
@Bill:是@Matteo Italia发现了格式问题导致缺少< >(这导致了几个错误答案,包括我的答案,现在已经删除)。当然,Matteo的答案最初是错误的,但后来得到了纠正。我的评论只是为了解决问题 ;) - phooji
5个回答

13

您试图使用没有排序的元素类型(std::pair),而 std::set 需要其元素具有“特定严格弱排序准则”。


更新:实际上,std::pair 提供了一个 operator<(感谢 @UncleBens),它是根据其组件的 operator< 定义的;因此问题在于您的 AB 没有提供比较运算符;您应该为 AB 编写一个 operator<

或者,由于对于点来说,operator< 通常并没有太多意义,您可以为您的 Point 创建一个比较函数对象,并将其作为第二个模板参数传递给 std::set


@Matteo Italia:很好的眼力,注意到(我猜)编译器错误缺少了尖括号 :) - phooji
3
实际上,std::pair 有排序。而 AB 没有。(请阅读错误信息。) - UncleBens
@phooji:实际上它走了另一条路;我注意到这篇文章有“奇怪”的#符号(它们是音乐符号而不是编程符号),所以我开始编辑问题来修复它们。在编辑时,我注意到代码是在<pre>块中,只有一些尖括号被替换为&gt;&lt;;保存编辑后,缺失的括号重新出现,使现有答案无效。 :) - Matteo Italia
1
如果你创建了一组成对的数据,只需要比较第一个元素的值,那么你刚刚创建了一个map。为什么不使用std::map呢? - Bo Persson

9

pairset 是模板而不是类。你需要这样做:

typedef pair<A, B> Point;
typedef set<Point> List;

当您实例化一个模板时,它就变成了一个类,例如:std::set<int> theset;创建了从类模板set创建set<int>

编辑:正如phooj所指出的那样,您需要A和B都有一个比较运算符operator<。请参见Matteo Italia的答案。


干得好,先生。你比我快了整整半分钟 :) - phooji
他发布的代码中有<A,B>,但由于他使用了<pre>标记而不是通常的4个空格,因此它们被Markdown删除了。问题在其他地方。 - Matteo Italia
@Eric:看起来实际问题在于 AB 没有满足可比较小于的概念。请参见我对问题的评论。 - phooji
@phooji:很好的观点。一旦他编辑代码与真实代码相匹配,那很可能就是下一个问题了。 - Erik
@Eric:看起来模板参数并不是问题的关键——仔细看一下编译器错误。 - phooji

4
#include <set>

int main(){

    typedef pair<int, int> pairs; //creating pair as default data type 
    pairs p[5]; //array of pair objects
    for (int i =0; i<5; i++){
        p[i].first= (i+1)*10; //inserting first element of pair
        p[i].second = (i+1); //inserting first element of pair
    }
    set<pairs> s;   //set to sort pair
    set<pairs> :: iterator it; //iterator to manipulate set

    for (int i =0; i<5; i++){
        s.insert(p[i]); //inserting pair object in set
    }

    for (it = s.begin(); it!=s.end(); it++){
        pairs m = *it; // returns pair to m

    cout<<m.first<<" "<<m.second<<endl; //showing pair elements
    }
    return 0;
}

1

你没有指定setpair元素的类型。

修改以下行:

typedef pair Point 改为 typedef pair<A, B> Pointtypedef set List 改为 typedef set<Point> List 可以解决你的问题。

一个吹毛求疵的评论:将set命名为List在阅读代码时会有些误导。


还有...也许要正确定义“点”吗? - phooji

1

对于任何存储在关联容器(如set/map)中的用户类型,其类型定义必须提供“<”操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接