2010-02-22 17 views
8

में std :: map तत्वों तक पहुंचने के लिए बाध्य करें मेरे पास एक नक्शा है जो एक कुंजी के साथ एक साधारण संरचना संग्रहीत करता है। संरचना में दो सदस्य कार्य हैं, एक दूसरा नहीं है। मैंने बिना किसी समस्या के std :: for_each का उपयोग करके कॉन्स्ट फ़ंक्शन को कॉल करने में कामयाब रहा है, लेकिन मुझे गैर-कॉन्स्ट फ़ंक्शन को कॉल करने में कुछ समस्याएं हैं।बूस्ट। Std :: for_each

struct MyStruct { 
    void someConstFunction() const; 
    void someFunction(); 
}; 

typedef std::map<int, MyStruct> MyMap; 
MyMap theMap; 

//call the const member function 
std::for_each(theMap.begin(), theMap.end(), 
    boost::bind(&MyStruct::someConstFunction, boost::bind(&MyMap::value_type::second, _1))); 

//call the non-const member function 
std::for_each(theMap.begin(), theMap.end(), 
    boost::bind(&MyStruct::someFunction, boost::bind(&MyMap::value_type::second, _1))); 

स्थिरांक सदस्य समारोह के लिए कॉल ठीक काम करता है, लेकिन यह को बढ़ावा देने लगता है आंतरिक रूप से कहीं न कहीं एक स्थिरांक MyStruct उम्मीद, और इस तरह MSVC7.1 में निम्नलिखित संकलन त्रुटि के साथ विफल।

बढ़ावा \ बाँध \ mem_fn_template.hpp (151): त्रुटि C2440: 'तर्क': 'MyStruct * स्थिरांक' को 'स्थिरांक MyStruct * __ W64' से परिवर्तित नहीं कर सकते

मैं किसी भी सराहनीय होगा टेम्पलेट पैरामीटर को सही तरीके से सेट करने के तरीके पर सहायता करें, इसलिए बाइंड सही ढंग से पैरामीटर को पहचानता है और मुझे गैर कॉन्स फ़ंक्शन को कॉल करने देता है।

धन्यवाद, कार्ल

+0

अगर आप बैक अप लें और हमें बताएं कि आप वास्तव में यहां क्या करने की कोशिश कर रहे हैं?बूस्ट :: बाइंड * हो सकता है * के साथ नक्शे के साथ for_each का उपयोग करना उचित हो सकता है, लेकिन संभावनाएं बहुत अच्छी हैं कि एक अलग सामान्य दृष्टिकोण बेहतर काम करेगा (कई बार इस प्रकार का सवाल उठता है, ऐसा इसलिए है क्योंकि 'std :: for_each' एक खराब विकल्प है स्थिति के लिए, और 'std :: copy' या std :: accumulate' जैसी कुछ चीज़ नौकरी को और अधिक सरलता से करेगी)। –

+0

MyStruct का उपयोग कण प्रणाली के प्रकार में किया जाता है, जहां MyStruct कण है। कॉन्स फ़ंक्शन एक ड्रॉ() फ़ंक्शन है, गैर-कॉन्स्ट फ़ंक्शन नई स्थिति की गणना करता है। मानचित्र में कुंजी निर्माण की तारीख है। वैसे भी, इस बिंदु पर मैंने सवाल पोस्ट किया था कि यह काम करने के तरीके के बारे में अधिक था, अगर यह शुरुआत में एक अच्छा डिजाइन था। – Carl

उत्तर

8

आईआईआरसी, बूस्ट। बाइंड सदस्यों की क्षमता के लिए बाध्यकारी के लिए boost::mem_fn का उपयोग करता है। अब, यदि आप mem_fun देखें (// data member support भाग पर नीचे स्क्रॉल करें), तो आप देखेंगे कि यह इसके परिणाम_ टाइप को कॉन्स & के रूप में टाइप किया गया है, जबकि अभी भी फ़ंक्शन कॉल ऑपरेटर का अधिभार है जो गैर-कॉन्स्ट सदस्य के निष्कर्षण का समर्थन करता है एक गैर-कॉन्स्ट तर्क।

ऐसा लगता है कि समस्या यह है कि यह बूस्ट को रोकता है। बाइंड की वापसी प्रकार कटौती तंत्र। इस प्रकार एक समाधान स्पष्ट रूप से बाइंड को बताना होगा कि परिणाम नहीं है:

//call the non-const member function 
std::for_each(theMap.begin(), theMap.end(), 
    boost::bind(&MyStruct::someFunction, 
     boost::bind<MyStruct&>(&MyMap::value_type::second, _1) 
    ) 
); 
+0

+1 नाइस जासूस काम के मामले में मदद नहीं करता है। :-) आश्चर्यजनक रूप से, 'boost :: lamba :: bind' का उपयोग करके रिटर्न प्रकार को स्पष्ट रूप से निर्दिष्ट किए बिना संकलित किया जाएगा। शायद 'बूस्ट :: lamda :: bind' वापसी प्रकारों को कम करने में' बूस्ट :: बाइंड 'से अधिक स्मार्ट है? –

+0

वाह, बहुत बहुत धन्यवाद। यह सिर्फ ठीक है। हालांकि मुझे बूस्ट का उपयोग करना अच्छा लगता है, लेकिन अभी भी मेरे अधिकांश कोड पढ़ने के लिए यह काफी मुश्किल है, इसलिए मैं असफल रहा। आपकी सहायता के लिए धन्यवाद. – Carl

+0

मुझे लगता है कि आपका मतलब है 'boost :: mem_fn' – Manuel

0

एक समस्या यह है कि मैं देखा: दूसरा बाँध एक गैर समारोह सदस्य के लिए कहा जाता है। दूसरा एक डेटा सदस्य नहीं एसटीडी की एक विधि :: जोड़ी

+3

मुझे इस आलेख में यह तकनीक मिली: http://www.informit.com/articles/article.aspx?p=412354&seqNum=4 यह कहता है "आप एक सदस्य चर के साथ बाध्य कर सकते हैं जैसे आप सदस्य फ़ंक्शन के साथ कर सकते हैं , या एक मुफ्त समारोह। " चूंकि for_each कोड अनिवार्य रूप से दोनों सदस्य कार्यों के लिए समान है और समस्या केवल गैर-कॉन्स्ट सदस्य फ़ंक्शन के कॉल में सामने आई है, मुझे लगता है कि आलेख सही है। – Carl

4

आप पहले से ही कर रहे हैं Boost पर निर्भर करते हैं, तो आप हालांकि मैं नहीं जानता, बहुत Boost Foreach

BOOST_FOREACH(MyMap::value_type const& val, MyMap) 
{ 
    val.second.someConstFunction(); 
} 

जाँच करने के लिए बहुत पठनीय तैयार हो सकता है है प्रदर्शन मुद्दों के बारे में।

भी ध्यान रखें कि आप बिना "से बचने" , चरित्र मैक्रो के भीतर आपके द्वारा लिखा गया टेम्प्लेटेड उपयोग नहीं कर सकते:

  • से पहले या प्रकार के आसपास कोष्ठक की एक दूसरी जोड़ी का उपयोग करके

    • या तो एक typedef द्वारा
  • +0

    मुझे बूस्ट Foreach पता है और वह निश्चित रूप से काम करता है। लेकिन मैं उपरोक्त समाधान के लिए सही वाक्यविन्यास खोजने के लिए उत्सुक हूं, क्योंकि ऊपर दिया गया कोड कॉन्स्ट फ़ंक्शन के लिए ठीक काम करता है और गैर-कॉन्स्टेंस के लिए विफल रहता है। – Carl

    +4

    मेरा मानना ​​है कि सही कोड होगा (यदि आप मानों को बदलना चाहते हैं तो कॉन्स्ट को हटाएं): BOOST_FOREACH (MyMap :: value_type const & val, theMap) {...} – Bklyn

    +0

    और आपको बढ़ावा देने के लिए लिंक करने की आवश्यकता नहीं है Boost.Bind या Boost का उपयोग करते समय। Foreach –

    7

    आप पाते हैं अपने आप को इस एक बहुत मैं तुम्हें Boost.RangeEx लाइब्रेरी का उपयोग की सलाह देते हैं क्या करने वाले हैं:

    #include <boost/range/algorithm/for_each.hpp> 
    #include <boost/range/adaptor/map.hpp> 
    #include <boost/mem_fn.hpp> 
    #include <map> 
    
    struct MyStruct { 
        void someConstFunction() const; 
        void someFunction(); 
    }; 
    
    typedef std::map<int, MyStruct> MyMap; 
    MyMap theMap; 
    
    int main() 
    { 
        //call the const member function 
        boost::for_each(theMap | boost::adaptors::map_values, 
            boost::mem_fn(&MyStruct::someConstFunction)); 
    
        //call the non-const member function 
        boost::for_each(theMap | boost::adaptors::map_values, 
            boost::mem_fn(&MyStruct::someFunction)); 
    } 
    

    इसे बूस्ट में स्वीकार कर लिया गया है लेकिन यह अभी तक आधिकारिक वितरण के साथ नहीं आया है। जब तक आप Boost Vault (ज़िप फ़ाइल से लिंक डाउनलोड करें) से download it कर सकते हैं।

    +0

    यह बाध्य समाधान की तुलना में बहुत अधिक पठनीय और समझ में आता है। यह निश्चित रूप से एक करीब देखो लायक है। पारितोषिक के लिए धन्यवाद। – Carl

    +0

    @ करल - यह भी ध्यान दें कि boost :: mem_fn को बढ़ावा देने के लिए उपयोग करना आसान है :: इस मामले में बाध्य करें – Manuel

    +0

    यह उत्तर प्रश्न के लिए ऑर्थोगोनल है, यह 'boost :: for_each' लूप को' boost :: for_each' द्वारा प्रतिस्थापित करता है, लेकिन यह नहीं बताता कि 'boost :: bind' को तर्क के रूप में कैसे उपयोग करें। फिर भी, यह एक कामकाज प्रदान करता है। –

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