2010-01-28 165 views
13

考慮類:我可以將參數傳遞給std :: vector排序函數嗎?

MyClass { 
    int varA; 
    int varB; 
}; 

我有一個指針的向量MYCLASS對象:

std::vector<MyClass*> Vec; 

我想根據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這是不可能的。如果不使用外部庫,最簡單的方法是什麼?

+1

你爲什麼使用指針對象的向量? – 2010-01-28 17:31:07

回答

21
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)); 
+1

+1非常好,你打我回答我的答案。我個人使'sorter'派生自'std :: binary_function ',但這是可選的。 – 2010-01-28 15:41:48

+0

是的,只有std :: bind1st或std :: bind2nd需要嵌套的typedefs,所以我省略了^ _ ^。 – OwnWaterloo 2010-01-28 15:52:55

+0

完美。謝謝。 – 2010-01-28 15:55:35

2

type的值是否隨每次比較而改變?它看起來不可能。在這種情況下,請使用咖喱功能 - 請參閱boost::bind

std::sort(v.begin(), v.end(), boost::bind(SortFunction, _1, _2, type)); 
+0

難道你不是指綁定(SortFunction,_1,_2,type)'? – 2010-01-28 15:43:55

+0

是的,太懶了... – dirkgently 2010-01-28 15:50:11

2

一個更通用的解決方案也可能是使用的指針到成員:

#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)); 
} 
6

就快,使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>); 

優化器會發現(type == VARA_ID)是編譯時常量。

+3

+1的想法,但我認爲你的意思是說'template '而不是'template '。 – 2010-01-28 16:13:09

+0

哎呀,是的。固定。 – MSalters 2010-01-29 08:42:07

3

使用Boost.Lambda和沒有任何特殊的排序功能,就在你的代碼,你需要排序:

簡言之

// 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)); 

完整的示例

#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; 
} 
相關問題