2009-03-04 9 views
27

std :: binary_function (या std :: unary_function) से विरासत का लाभ क्या है?std :: binary_function (या std :: unary function) से विरासत का लाभ क्या है?

उदाहरण के लिए मैं इस तरह के कोड है:

class Person 
{ 
public: 
    Person(); 
    Person(int a, std::string n); 
    Person(const Person& src); 

    int age; 
    std::string name; 
}; 

Person::Person() 
      : age(0) 
      , name("") 
       {}; 

Person::Person(int a, std::string n) 
: age(a) 
, name(n) 
{}; 

Person::Person(const Person& src) 
{ 
    age = src.age; 
    name = src.name; 
}; 

struct PersonPrint : public std::unary_function<Person, void>{ 
    void operator() (Person p){ 
    std::cout << " Person age: " << p.age 
       << " name: " << p.name << std::endl; 
    } 
}; 

struct PersonGreater : public std::binary_function<Person, Person, bool>{ 
    bool operator()(const Person& p1, const Person p2){ 
    if (p1.age > p2.age) return true; 
    if (p1.name.compare(p2.name) > 0) return true; 
    return false; 
    } 
}; 

int main(int count, char** args) 
{ 
    std::vector<Person> personVec; 
    Person p1(10, "Person1"); 
    Person p2(12, "Person2"); 
    Person p3(12, "Person3"); 

    personVec.push_back(p1); 
    personVec.push_back(p2); 
    personVec.push_back(p3); 

    std::cout << "before sort: " << std::endl; 
    std::for_each(personVec.begin(), personVec.end(), PersonPrint()); 
    std::sort(personVec.begin(), personVec.end(), PersonGreater()); 
    std::cout << "after: " << std::endl; 
    std::for_each(personVec.begin(), personVec.end(), PersonPrint()); 
} 

लेकिन मैं यह भी विरासत रूप std::unary_function/std::binary_function के बिना इस कोड लिख सकता है?

struct PersonPrint { 
    void operator() (Person p) { 
     std::cout << " Person age: " << p.age << " name: " << p.name << std::endl; 
    } 
}; 

struct PersonGreater { 
    bool operator()(const Person& p1, const Person p2) { 
     if (p1.age > p2.age) return true; 
     if (p1.name.compare(p2.name) > 0) return true; 
     return false; 
    } 
}; 

std :: binary_function और std :: unary_function @AlexandreC द्वारा सी ++ 11 देखते हैं कि टिप्पणी के रूप में अनुचित हैं अद्यतन किया गया। के लिए binary_function

first_argument_type 
second_argument_type 
result_type 

कौन उन प्रकार आप पारित कर रहे हैं

लिए unary_function

argument_type 
result_type 

: |

से
+2

उन्हें सी ++ 11 में बहिष्कृत कर दिया गया है (बेशक, प्रश्न पूछे जाने पर कोई सी ++ 11 नहीं था)। –

+0

@AlexandreC। इसके बजाय हमें क्या उपयोग करना चाहिए? सी ++ कोडिंग मानकों में, एंड्रेई ने उल्लेख किया कि वे स्टर्ल एल्गोरिदम –

+0

@kirill_igum के साथ उपयोग करने के लिए मज़ेदार बनाने के लिए महत्वपूर्ण हैं: अब 'decltype', 'auto' और' std :: result_of' उपलब्ध हैं, आपको विरासत की आवश्यकता नहीं है कुछ भी। इसके अलावा, 'बाइंड 1' और 'bind2nd' को 'बाइंड' के पक्ष में बहिष्कृत कर दिया गया है। –

उत्तर

29

विरासत [एकल द्विआधारी] _function केवल आपके अपनी कक्षा में एक अतिरिक्त typedefs देता है [unary | बाइनरी] _ समारोह के लिए। आपके मामले में कोई लाभ नहीं है।

यदि आप कभी भी अपने कर्मचारियों को अन्य std Functors modificators के साथ उपयोग करने के लिए नहीं जा रहे हैं, तो 1, bind1st आपको [unart | binart] _function से प्राप्त करना होगा।

और यदि आप अपने उद्देश्य के लिए इस टेम्पलेट की जानकारी को स्टोर करने जा रहे हैं तो तैयार समाधान का उपयोग करना बेहतर है।

+1

आपको ध्यान रखना चाहिए कि इन typedefs का उपयोग एसटीएल कार्यात्मक पुस्तकालय द्वारा किया जाता है, उदाहरण के लिए negators not1 और not2। –

+0

@Luc: नोटिस के लिए धन्यवाद। –

9

माइकोला की तरह बताते हैं, वे सिर्फ टाइपपीफ जोड़ रहे हैं। अपने PersonGreater के लिए कल्पना करें, आप किसी व्यक्ति को पहला तर्क ठीक करना चाहते हैं। binder1st को पहले तर्क को कहीं भी स्टोर करने की आवश्यकता होगी, और इसलिए इसे पहले तर्क के प्रकार की आवश्यकता है।

// get a function object that compares person1 against 
// another person 
std::bind1st(PersonGreater(), person1) 

अब, लौटे binder1st वस्तु जानता है कि तर्क यह संग्रहीत करने की आवश्यकता के प्रकार के प्रकार व्यक्ति का है: binary_function एक typedef के रूप में है कि प्रदान करता है।

कुछ फ़ंक्शन ऑब्जेक्ट्स किसी अन्य फ़ंक्शन ऑब्जेक्ट के परिणाम को अस्वीकार करते हैं। यहाँ हम भी तर्क के प्रकार की जरूरत है:

template <class Predicate> 
class unary_negate 
    : public unary_function<typename Predicate::argument_type,bool> { 
    Predicate pred; 
public: 
    explicit unary_negate(const Predicate& pred):pred(pred) { } 
    bool operator()(const typename Predicate::argument_type& x) const { 
     return !pred(x); 
    } 
}; 

कि यह भी एक टेम्प्लेटेड operator() इस्तेमाल कर सकते हैं, लेकिन Standard यह पैरामीटर के रूप में argument_type प्रकार का उपयोग करने को परिभाषित करता है। नियामक स्वयं unary_function से लिया गया है और वैसे भी पहले तर्क प्रकार प्रदान करने की जरूरत है।

कभी-कभी, लोग कार्य वस्तुओं/पॉइंटर्स को संग्रहीत करने के लिए [unary,binary]_function का उपयोग करने का प्रयास करते हैं। हालांकि, उनके लिए इसका उपयोग नहीं किया जा सकता है। boost::function उस नौकरी को पूरा करता है और अगले मानक में std::function के रूप में अपनाया जाएगा।

+0

@litb: bind1st के बारे में अच्छा बिंदु। Bind1st के साथ कभी भी मेरे ऑब्जेक्ट फ़ैक्टर का उपयोग नहीं किया। –

16

टाइपपीफ (पहले से ही उल्लेख किया गया) के अलावा, पठनीयता के पहलू के रूप में भी है। जब मुझे struct Foo {... दिखाई देता है तो मेरा पहला विचार "फू एक प्रकार" होगा। लेकिन struct Foo : public unary_function<... के साथ मुझे पहले से ही पता है कि फू एक मजेदार है। एक प्रोग्रामर (कंपाइलर्स के विपरीत) के लिए, प्रकार और मज़ेदार काफी अलग हैं।

+6

सख्त होने के लिए, फू कभी एक मजेदार नहीं है। यह या तो एक प्रकार है, या, विशेष रूप से, एक मजेदार * प्रकार *। फंक्शंस खुद मज़ेदार प्रकार के तत्काल हैं। –

3

यह संकलक द्वारा लागू प्रलेखन का एक मजबूत रूप है।

विरासत में, आप एक वादा कर रहे हैं कि आप बाइनरी_फंक्शन इंटरफेस को लागू करेंगे, और संकलक आपको इसे पकड़ लेगा। फिर, ग्राहक भरोसा कर सकते हैं कि जहां भी बाइनरी_फंक्शन की आवश्यकता होती है, आपकी कक्षा का उपयोग किया जा सकता है।

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