[英]Can I pass a parameter to an std::vector sort function?
Consider the class: 考虑一下类:
MyClass {
int varA;
int varB;
};
I have a vector of pointers to MyClass objects: 我有一个指向MyClass对象的指针向量:
std::vector<MyClass*> Vec;
I want to sort the vector according to varA or varB using the same sort function, ie : 我想使用相同的排序功能,根据varA或varB对向量进行排序,即:
bool SortFunction(const MyClass* obj1, const MyClass* obj2, const short type) {
if( type == VARA_ID )
return obj1->varA < obj2->varA;
else if( type == VARB_ID )
return obj1->varB < obj2->varB;
}
AFAICT this is not possible. AFAICT这是不可能的。 What would be the most elegant way to this without using external libraries? 不使用外部库,最优雅的方法是什么?
class sorter {
short type_;
public:
sorter(short type) : type_(type) {}
bool operator()(MyClass const* o1, MyClass const* o2) const {
return SortFunction(o1, o2, type_ );
}
};
std::sort(Vec.begin(), Vec.end(), sorter(MY_TYPE) );
You're almost there, make type
a template parameter and the signature is OK: 您快到了, type
作为模板参数,签名就可以了:
template<int type>
bool SortFunction(const MyClass* obj1, const MyClass* obj2) {
if( type == VARA_ID )
return obj1->varA < obj2->varA;
else // if( type == VARB_ID ) -- A sort function must have a default.
return obj1->varB < obj2->varB;
}
std::sort(Vec.begin(), Vec.end(), &SortFunction<VARA_ID> );
The optimizer will spot that ( type == VARA_ID )
is a compile-time constant. 优化器将发现( type == VARA_ID )
是编译时常量。
Using Boost.Lambda and without any special sorting function , right in your code where you need sorting: 使用Boost.Lambda并且没有任何特殊的排序功能 ,就在您需要排序的代码中:
Briefly 简要地
// sort with VARA_ID
sort(Vec.begin(), Vec.end(), bind(&MyClass::varA, _1)<bind(&MyClass::varA, _2));
// sort with VARB_ID
sort(Vec.begin(), Vec.end(), bind(&MyClass::varB, _1)<bind(&MyClass::varB, _2));
Full example 完整的例子
#include <iostream>
#include <vector>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <algorithm>
using namespace boost::lambda;
class MyClass {
public:
int varA;
int varB;
};
enum SorterType {
VARA_ID,
VARB_ID
};
int main()
{
std::vector<MyClass*> Vec;
Vec.push_back(new MyClass());
Vec.push_back(new MyClass());
Vec.push_back(new MyClass());
Vec[0]->varA = 1; Vec[0]->varB = 8;
Vec[1]->varA = 2; Vec[1]->varB = 7;
Vec[2]->varA = 3; Vec[2]->varB = 6;
// sort with VARA_ID
std::sort(Vec.begin(), Vec.end(),
bind(&MyClass::varA, _1) < bind(&MyClass::varA, _2) );
// VARB_ID
std::sort(Vec.begin(), Vec.end(),
bind(&MyClass::varB, _1) < bind(&MyClass::varB, _2) );
return 0;
}
Does the value of type
change with each comparison? type
值是否随每次比较而变化? It cannot, as it appears. 看起来好像不能。 In that case, use a curried function -- see boost::bind
. 在这种情况下,请使用curried函数-请参见boost::bind
。
std::sort(v.begin(), v.end(), boost::bind(SortFunction, _1, _2, type));
A more generic solution might also be to make use of pointers-to-members: 一个更通用的解决方案也可能是使用指向成员的指针:
#include <vector>
#include <algorithm>
#include <functional>
struct MyClass {
int varA;
int varB;
};
template <class Object, class VarType>
class CompareMemberT: public std::binary_function<bool, const Object*, const Object*>
{
VarType Object::*p;
public:
CompareMemberT(VarType Object::*p): p(p) {}
bool operator()(const Object* a, const Object* b) const
{
return a->*p < b->*p;
}
};
//helper to deduce template arguments
template <class Object, class VarType>
CompareMemberT<Object, VarType> CompareMember(VarType Object::*p)
{
return CompareMemberT<Object, VarType>(p);
}
int main()
{
std::vector<MyClass*> vec;
std::sort(vec.begin(), vec.end(), CompareMember(&MyClass::varA));
std::sort(vec.begin(), vec.end(), CompareMember(&MyClass::varB));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.