2010-01-28 13 views
13

वर्ग पर विचार करें:क्या मैं एक std :: वेक्टर सॉर्ट फ़ंक्शन पर पैरामीटर पास कर सकता हूं?

std::vector<MyClass*> Vec; 

मैं Vara या varB इसी तरह समारोह, यानी का उपयोग कर के अनुसार वेक्टर क्रमबद्ध करना चाहते हैं:

MyClass { 
    int varA; 
    int varB; 
}; 

मैं संकेत का एक वेक्टर वस्तुओं MyClass के लिए है

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 बहुत अच्छा, आपने मुझे मेरे जवाब में हराया। मैं 'storter :: binary_function ' से व्यक्तिगत रूप से 'सॉर्टर' प्राप्त करता हूं, लेकिन यह वैकल्पिक है। –

+0

हां, नेस्टेड टाइपपीफ केवल std :: bind1st या std :: bind2nd द्वारा आवश्यक है, इसलिए मैंने इसे छोड़ दिया^_ ^। – OwnWaterloo

+0

बिल्कुल सही। धन्यवाद। –

2

क्या type का मान प्रत्येक तुलना के साथ बदलता है? ऐसा नहीं हो सकता है, जैसा कि यह प्रतीत होता है। उस स्थिति में, एक करीबी फ़ंक्शन का उपयोग करें - boost::bind देखें।

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

क्या आपका मतलब नहीं है 'बाध्य (सॉर्टफंक्शन, _1, _2, प्रकार)'? –

+0

हाँ, बहुत आलसी ... – dirkgently

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 के लिए अधिक उपयुक्त है, हालांकि मुझे लगता है कि आप 'टेम्पलेट <टाइपनाम प्रकार>' के बजाय 'टेम्पलेट ' कहने के लिए चाहते हैं। –

+0

ओह, हाँ। फिक्स्ड। – MSalters

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; 
} 
संबंधित मुद्दे

 संबंधित मुद्दे