将参数传递给比较函数?

时间:2010-11-01 04:08:05

标签: c++ sorting stl

在向量上使用STL排序算法时,我想传入我自己的比较函数,该函数也需要参数。

例如,理想情况下我想做一个本地函数声明,如:

int main() {
    vector<int> v(100);
    // initialize v with some random values

    int paramA = 4;

    bool comp(int i, int j) {
        // logic uses paramA in some way...
    }

    sort(v.begin(), v.end(), comp);
}

然而,编译器抱怨这一点。当我尝试类似的东西时:

int main() {
    vector<int> v(100);
    // initialize v with some random values

    int paramA = 4;

    struct Local {
        static bool Compare(int i, int j) {
            // logic uses paramA in some way...
        }
    };

    sort(v.begin(), v.end(), Local::Compare);
}

编译器仍然抱怨:“错误:使用包含函数的参数”

我该怎么办?我应该使用全局比较函数制作一些全局变量吗?

感谢。

4 个答案:

答案 0 :(得分:27)

您无法从本地定义的函数中访问函数的局部变量 - 当前形式的C ++不允许closures。该语言的下一个版本C ++ 0x将支持此功能,但语言标准尚未最终确定,目前对当前的标准草案几乎没有支持。

要使其工作,您应该将std::sort的第三个参数更改为对象实例而不是函数。 std::sort的第三个参数可以是任何可调用的参数(即任何x,其中添加括号如x(y, z)使语法有意义)。执行此操作的最佳方法是定义实现operator()函数的结构,然后传递该对象的实例:

struct Local {
    Local(int paramA) { this->paramA = paramA; }
    bool operator () (int i, int j) { ... }

    int paramA;
};

sort(v.begin(), v.end(), Local(paramA));

请注意,我们必须在结构中存储paramA,因为我们无法从operator()内访问它。

答案 1 :(得分:12)

在C ++中,您无法在另一个函数中定义自由函数。因此,您的第一个代码段形成错误。

  

sort(v.begin(),v.end(),Local :: Compare);

第三个参数必须是一个函数对象。在类中重载()运算符,然后创建函数对象。


在C ++ 0x中,您可以使用lambda expressions

auto comp = [&](int m,int n)-> bool {

        return m<n; //or use paramA in some way
    };

sort(v.begin(), v.end(), comp);

答案 2 :(得分:5)

一种可能性是在构造比较器对象时传递参数:

class cmp {
    int param;
public:
    cmp(int p) : param(p) {}

    bool operator()(int i, int j) {
        // logic uses param
    }
};

int main() {
    vector<int> v(100);
    // initialize v with some random values

    int paramA = 4;

    sort(v.begin(), v.end(), cmp(paramA));
}

答案 3 :(得分:0)

//使用std :: bind

//示例

{
vector<int> vecInt{2, 4, 10, 20, 30};
    int i = 4;
    sort(vecInt.begin(), vecInt.end(), std::bind( [](int a, int b, int c)
    {
        return abs(a - c) < abs(b - c);
    }, std::placeholders::_1, std::placeholders::_2, i)
    );
}