2010-01-28 4 views
13

std :: vector sort 함수에 매개 변수를 전달할 수 있습니까?

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

왜 포인터 객체의 벡터를 사용합니까? –

답변

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 아주 좋아요, 당신이 저를 제 대답에 이겼습니다. 나는 개인적으로'sord'를'std :: binary_function '에서 파생시킬 것이지만, 여기서는 선택 사항입니다. –

+0

예, 중첩 된 typedef는 std :: bind1st 또는 std :: bind2nd에서만 필요하므로^_ ^을 생략했습니다. – OwnWaterloo

+0

완벽합니다. 감사. –

2

각 비교에서 type의 값이 변경됩니까? 그것은 나타날 수 없습니다. 이 경우 카레 함수를 사용하십시오 (boost::bind 참조).

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

'bind (SortFunction, _1, _2, type)'을 의미하지 않습니까? –

+0

예, 너무 게으른 ... – dirkgently

2

더 일반적인 솔루션은 사용 포인터 - 투 - 회원 만들 수 있습니다 : type 템플릿 매개 변수를 만드는 당신은 거의 다

#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

과 서명은 OK입니다 :

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)는 컴파일 타임 상수가 있음을 발견 할 것이다. 바로 당신을 정렬해야 할 코드에서, 특별한 정렬 기능없이 Boost.Lambda 및 를 사용

+3

+1에 더 적합합니다. 그러나 'template 대신'template '을 말하려고 생각합니다. –

+0

죄송합니다. 결정된. – MSalters

3

:

간단히

// 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; 
} 
관련 문제