2011-12-12 12 views
5

मेरे पास निम्न प्रोग्राम है जो lambda फ़ंक्शन के साथ ptr_fun का उपयोग करता है।ptr_fun एक लैम्ब्डा फ़ंक्शन के साथ

#include <iostream> 
#include <vector> 
#include <algorithm> 
#include <string> 
#include <cstring> 

using namespace std; 
int main() 
{ 
    string target="aa"; 
    vector<string> v1; 
    v1.push_back("aa"); 
    v1.push_back("bb"); 
    auto stringcasecmp=[](string lhs, string rhs)->int 
    { 
     return strcasecmp(lhs.c_str(), rhs.c_str()); 
    }; 

    auto pos = find_if(
     v1.begin(), v1.end(), 
     not1(bind2nd(ptr_fun(stringcasecmp), target)) 
     ); 

    if (pos != v1.end()) 
    cout << "The search for `" << target << "' was successful.\n" 
     "The next string is: `" << pos[1] << "'.\n"; 
} 

मुझे निम्न त्रुटि संदेश मिलते हैं।

stackoverflow.cpp: In function ‘int main()’: 
stackoverflow.cpp:21:41: error: no matching function for call to ‘ptr_fun(main()::<lambda(std::string, std::string)>&)’ 
stackoverflow.cpp:22:6: error: unable to deduce ‘auto’ from ‘<expression error>’ 

मैं इसे संकलित करने के लिए कोड (न्यूनतम) कैसे संशोधित करूं?

+1

बस एक छोटे से sidenote: यदि आप एक तरह एक लैम्ब्डा के प्रयोग पर योजना बना रहे हैं आप यहाँ एक बहुत, तुम हो सकता है संदर्भ के रूप में तर्क पारित करने पर विचार करें। स्ट्रिंग प्रतिलिपि के बहुत से बचाओ। –

+0

आपको लगता है कि आपका 'स्ट्रिंगकेसंप' लैम्ब्डा रिकर्सिव है! – quamrana

+0

@quamrana यह रिकर्सिव क्यों है? – ggg

उत्तर

9

bind2nd (§D.9) और ptr_fun (§D.8.2.1) C++ 11 में बहिष्कृत हैं। तुम बस find_if में एक और लैम्ब्डा समारोह लिख सकते हैं:

auto pos = find_if(v1.begin(), v1.end(), 
        [&](const std::string& s) { 
         return !stringcasecmp(s, target); 
        }); 

ptr_fun(<lambda>) काम नहीं करेगा, क्योंकि ptr_fun सी ++ 03 अन्य एडाप्टर के लिए एक समारोह वस्तु के लिए एक समारोह सूचक कन्वर्ट करने के लिए बनाया गया है। एक लैम्ब्डा पहले से ही एक फ़ंक्शन ऑब्जेक्ट है, इसलिए ptr_fun अनावश्यक है।

bind2nd समारोह वस्तु सदस्यों second_argument_type और result_type है, जो एक लैम्ब्डा लिए सही नहीं है परिभाषित करने के लिए है, तो bind2nd(<lambda>, target) लेखन या तो काम नहीं करेगा उम्मीद है। लेकिन C++ 11 एक सामान्य प्रतिस्थापन कि काम करता है:

std::bind(stringcasecmp, std::placeholders::_1, target) 

हालांकि, bind एक सी ++ 03 शैली समारोह वस्तु वापस नहीं करता है, जो not1 उम्मीद कर रही है: यह bind का परिणाम के प्रकार की आवश्यकता है argument_type सदस्य को परिभाषित करने के लिए जो मौजूद नहीं है। इसलिए अंतिम अभिव्यक्ति

std::not1(std::bind(stringcasecmp, std::placeholders::_1, target)) 

नहीं कार्य नहीं करेगा। सबसे सरल कामकाज सिर्फ ऊपर लिखा गया एक और लैम्ब्डा है।

वैकल्पिक रूप से, आप एक सामान्य negator निर्धारित कर सकते हैं:

template <typename Predicate> 
struct generic_negate 
{ 
    explicit generic_negate(Predicate pred) : _pred(pred) {} 

    template <typename... Args> 
    bool operator()(Args&&... args) 
    { 
     return !_pred(std::forward<Args>(args)...); 
    } 
private: 
    Predicate _pred; 
}; 

template <class Predicate> 
generic_negate<Predicate> not_(Predicate pred) 
{ 
    return generic_negate<Predicate>(pred); 
} 

.... 

auto pos = find_if(v1.begin(), v1.end(), not_(bind(stringcasecmp, _1, target))); 

उदाहरण: http://ideone.com/6dktf

+0

धन्यवाद बन गया। मुझे लगता है कि यह अजीब बात है कि bind2nd को बहिष्कृत किया गया है, लेकिन सी ++ 11 बाइंड 1 के साथ काम नहीं करता है। – ggg

+0

"*' ptr_fun () 'काम नहीं करेगा, क्योंकि' ptr_fun' को अन्य एडाप्टर के लिए फ़ंक्शन पॉइंटर को फ़ंक्शन ऑब्जेक्ट में कनवर्ट करने के लिए C++ 03 के लिए डिज़ाइन किया गया है। * "कैप्चर किए जाने के बावजूद यह क्यों काम नहीं करना चाहिए लैम्बडास फंक्शन पॉइंटर्स के लिए पूरी तरह से परिवर्तनीय हैं? – ildjarn

+1

@ildjarn: मुझे नहीं लगता कि एक रूपांतरण ऑपरेटर टेम्पलेट तर्क कटौती में भाग लेगा। – kennytm

0

ptr_fun(stringcasecmp) के बजाय pointer_to_binary_function<string,string,int>(stringcasecmp) आज़माएं?

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