带有类键和类值的C++ STL映射容器

pet*_*mlm 5 c++ containers map

所以假设我有一个像这样的课程:

class Point
{
   private:
      int x, y;
   public:
      void setX(int arg_x) { x = arg_x; }
      void sety(int arg_y) { y = arg_y; }
      int getX() const { return x; }
      int gety() const { return y; }
};
Run Code Online (Sandbox Code Playgroud)

现在我想要一张这样的地图:

map<Point, Point> m;
Run Code Online (Sandbox Code Playgroud)

但我需要第三个参数.我在cplusplus中读到第三个参数是比较一些东西,但我不明白那是什么东西.任何人都能解释一下吗?

par*_*mar 22

如果不需要单独的比较函数,可以使用这种方法扩展类

class Point
{
   private:
      int x, y;
   public:

      bool operator<( const Point& other) const
      {
          if ( x == other.x )
          {
              return y < other.y;
          }

          return x < other.x;
      }
};
Run Code Online (Sandbox Code Playgroud)

默认情况下,stl映射通过一些排序概念对其中的所有元素进行排序.在这种情况下,使用此运算符.有时您无法控制Point类,或者您可能希望在两个不同的映射中使用它,每个映射都定义自己的顺序.例如,一个地图可能先按x对点进行排序,而另一个可能先按y排序.因此,如果比较运算符独立于Point类,则可能会有所帮助.你可以做这样的事情.

class Point
{
   public:
      int x, y;
};


struct PointComparer
{
    bool operator()( const Point& first , const Point& second) const
    {
        if ( first.x == second.x )
        {
            return first.y < second.y;
        }

        return first.x < second.x;
    }
};

map<Point, Point , PointComparer> m;
Run Code Online (Sandbox Code Playgroud)


pae*_*bal 9

您需要的是定义Point项的排序.

这可以通过不同方式完成:

重载operator <for Point

您可以提供<操作员的重载,其原型是:

bool operator < (const Point & p_lhs, const Point & p_rhs) ;
Run Code Online (Sandbox Code Playgroud)

例如,对于我的测试,我使用了以下一个:

bool operator < (const Point & p_lhs, const Point & p_rhs)
{
    if(p_lhs.getX() < p_rhs.getX()) { return true ; }
    if(p_lhs.getX() > p_rhs.getX()) { return false ; }
    return (p_lhs.getY() < p_rhs.getY()) ;
}
Run Code Online (Sandbox Code Playgroud)

这是最简单的方法,但它在语义上假设上面定义的顺序是正确的默认顺序.

提供一个仿函数

如果您不愿意提供<操作员,或者想要拥有多个地图,每个地图都有自己的排序,那么您的解决方案就是为地图提供一个仿函数.这是为地图定义的第三个模板参数:

template < class Key, class T, class Compare = less<Key>,
       class Allocator = allocator<pair<const Key,T> > > class map;
Run Code Online (Sandbox Code Playgroud)

仿函数必须具有以下签名:

struct MyCompareFunctor
{
    bool operator() (const Point & p_lhs, const Point & p_rhs)
    {
       // the code for comparison
    }
} ;
Run Code Online (Sandbox Code Playgroud)

所以,对于我的测试,我只写了以下内容:

struct MyCompare
{
    bool operator() (const Point & p_lhs, const Point & p_rhs)
    {
        if(p_lhs.getX() > p_rhs.getX()) { return true ; }
        if(p_lhs.getX() < p_rhs.getX()) { return false ; }
        return (p_lhs.getY() > p_rhs.getY()) ;
    }
} ;
Run Code Online (Sandbox Code Playgroud)

并在我的地图中使用它:

std::map<Point, Point, MyCompare> map ;
Run Code Online (Sandbox Code Playgroud)

Etvoilà......

专业std::lessPoint

我认为这样做没有意义,但总是很高兴知道:你可以专门std::less为你的Point班级设计模板结构

#include <functional>

namespace std
{
    template<>
    struct less<Point> : binary_function <Point,Point,bool>
    {
        bool operator() (const Point & p_lhs, const Point & p_rhs)
        {
            if(p_lhs.getX() < p_rhs.getX()) { return true ; }
            if(p_lhs.getX() > p_rhs.getX()) { return false ; }
            return (p_lhs.getY() < p_rhs.getY()) ;
        }
    } ;
}
Run Code Online (Sandbox Code Playgroud)

operator <地图而言,这至少与重载相同.

至于operator <上面的解决方案,从语义上讲,这个解决方案假定上面定义的顺序是正确的默认顺序std:less.

请注意,默认std::less实现调用operator <的是模板化类型.让一个给出不同于另一个的结果可以被认为是语义错误.