根据非静态值对结构进行排序 (C++)

Sort structs depending on non-static value (C++)

我有一个 EnemyRhombus class。它是一个单位,可以移动到地图上的不同点。

我想处理它可以移动到的点,按照与它们的距离增加的顺序。

为此,我想对这些点进行排序。

代码 1:

class EnemyRhombus
{
public:
    int x,y;
    int dist(Point p)
    {
        int dx=abs(p.x-x);
        int dy=abs(p.y-y);
        return dx+dy-min(dx,dy);
    }
    bool points_cmp(Point f, Point s)
    {
        return dist(f)<dist(s);
    }
    void move()
    {
        vector<Point> candidates;
        //...
        sort(candidates.begin(),candidates.end(),points_cmp);
    }
}

不编译。打印

[错误] 没有匹配函数来调用 'sort(std::vector::iterator, std::vector::iterator, < unresolved overloaded function type>)'

代码 2:

class EnemyRhombus
{
public:
    int x,y;
    static int dist(Point p, int tx, int ty)
    {
        int dx=abs(p.x-tx);
        int dy=abs(p.y-ty);
        return dx+dy-min(dx,dy);
    }
    template<int X, int Y> static bool points_cmp(Point f, Point s) 
    {
        return dist(f,X,Y)<dist(s,X,Y);
    }
    void move()
    {
        vector<Point> candidates;
        //...
        sort(candidates.begin(),candidates.end(),points_cmp<x,y>);
    }
}

产生错误:

[错误] 'EnemyRhombus::x' 不能出现在常量表达式中

[错误] 'EnemyRhombus::y' 不能出现在常量表达式中


我该如何解决这个问题?


使用答案中的示例可能会产生错误和警告,说默认情况下启用 c++ 11,这是不正确的(至少在 orwell dev-cpp 中)。 为了使它们工作,应该将 -std=c++11 添加到编译器命令中。 (在我的例子中,工具->编译器选项-> Genera)

std::sort 不能使用 points_cmp 因为它没有 this 指针,因为您正试图将指针传递给成员函数,所以

如果你的编译器支持C++11,你可以使用:

std::sort( candidates.begin(),
           candidates.end(),
           bind(&EnemyRhombus::points_cmp, this, _1, _2));

否则创建函数 static 或 class

中的自由函数

除了使用 static/out-of-class 函数或使用 P0W 建议的方法外,您还可以使用 C++11 lambda。

std::sort(candidates.begin(),candidates.end(),
    [&](Point f, Point s) { return dist(f) < dist(s); }
);

lambda 负责排序的顺序。

在代码 1 的情况下,c++14 允许做得更好:

std::sort(candidates.begin(), candidates.end(), [this] (auto a, auto b) {
  return points_cmp(a, b);
});

您可以考虑使用 lambda 以自定义方式对 vector<Point> 进行排序;可以在 lambda 主体中指定自定义排序顺序(请注意,lambda 从 C++11 开始可用):

void move()
{
    std::vector<Point> candidates;
    //...

    //
    // Specify your custom sorting using a lambda:
    // 
    std::sort(candidates.begin(), candidates.end(), [this](Point f, Point s) {
        return dist(f) < dist(s);
    });
}

另请注意,在 lambda 中,您必须使用 [this] capture 语法,因为您正在调用 dist() lambda 体内的非静态成员函数。


此外,如果您的 Point class 复制起来 便宜,请考虑使用 const& 传递它(以避免无用的 "deep copies"):

std::sort(candidates.begin(), 
          candidates.end(), 
          [this](const Point& f, const Point& s) {
              return dist(f) < dist(s);
          }
);