2009-04-06 12 views
6
का उपयोग कर

मैं एक, नक्शे में तत्वों की राशि जमा मूल्य

struct SMyStruct 
{ 
    int MULT; 
    int VAL; 

}; 


std::map<std::string, SMyStuct*> _idToMyStructMap; 

है अब मैं सभी SMyStuct, जहां कुल में प्रत्येक तत्व के लिए के रूप में MULT1 * VAL1 + MULT2 * VAL2 परिभाषित किया गया है की कुल गणना करना चाहते कहो idToMyStructMap।

लगता संचित समारोह की तरह एक प्राकृतिक विकल्प है। कृपया सुझाव दे। धन्यवाद

नहीं बूस्ट कृपया .... सिर्फ एक 'ld फैशन एसटीएल

+0

अरे, बीबी ने मुझे जवाब में हरा दिया, इसलिए मैं इसके बजाय थोड़ा सा पैडेंटिक होने जा रहा हूं: आप जानते हैं कि अग्रणी अंडरस्कोर आम तौर पर एक बुरा विचार है, है ना? (ज्यादातर मामलों में कार्यान्वयन के लिए आरक्षित) और एक संरचना पर एस उपसर्ग पूरी तरह से व्यर्थ शोर है। :) – jalf

+0

अरे, ठीक है ... ठीक है हम एस के साथ हमेशा उपसर्ग structs और वर्गों सी के साथ; हमारे कोडिंग मानक जनादेश। "_" के रूप में, मैं सहमत हूं लेकिन चूंकि यह किसी भी चीज़ का हिस्सा नहीं था, इसलिए मैंने इसे छोड़ दिया। मैं आम तौर पर ग्लोबल्स के लिए सदस्यों g_ और स्थिर के लिए s_ के लिए m_ का उपयोग करता हूं। इस पर ध्यान दिलाने के लिए धन्यवाद। –

+0

_ * शायद * तकनीकी रूप से ठीक हो सकता है। नियम कुछ ऐसा हैं जैसे "डबल अग्रणी _ या अग्रणी _ पूंजी पत्र के बाद कार्यान्वयन के लिए आरक्षित है। अग्रणी _ वैश्विक नामस्थान में आरक्षित है।"सबसे आसान सिर्फ प्रमुख से बचने के लिए _ पूरी तरह है;) – jalf

उत्तर

13
typedef std::map< std::string, SMyStruct* > string_to_struct_t; 

int add_to_totals(int total, const string_to_struct_t::value_type& data) 
{ 
    return total + data.second->MULT * data.second->VAL; 
} 

const int total = std::accumulate(
         _idToMyStructMap.begin(), 
         _idToMyStructMap.end(), 
         0, 
         add_to_totals); 
+0

awm, आप मुझे इसे हराया। +1 – jalf

+1

ऑपरेटर() के साथ ऑब्जेक्ट के रूप में add_to_totals लिखने के लिए और अधिक कुशल होगा। अन्यथा, अच्छा समाधान। – PaulJWilliams

+0

@ विज़िट, और अधिक कुशल क्यों? इस मामले strucutre में की जरूरत नहीं है .. – bayda

6

विषय पर एक बदलाव ऑपरेटर + अपने struct के लिए परिभाषित करने के लिए हो सकता है, और फिर बस एसटीडी का उपयोग :: में जमा इसका डिफ़ॉल्ट मोड।

int & operator+ (const int &lhs, const SMyStruct &rhs){ 
    return lhs + (rhs.MULT * rhs.VALUE); 
} 
फिर

:

std::accumulate(_idToMyStructMap.begin(), _idToMyStructMap.end(), 0); 
बेशक

, अगर operator+ अपने struct के लिए सामान्य रूप में समझ में आता है, तो आप के रूप में अच्छी छोड़ दिया पर SMyStruct प्रयोग करने के लिए भार के जोड़ सकते हैं, और/या बनाने उन्हें टेम्पलेट्स ताकि आप एक शॉट में int, float, double, long, आदि के लिए फ़ंक्शंस प्राप्त कर सकें। टिप्पणियों में आधे उल्लेख के रूप में, यदि operator+ (या इसका यह संस्करण) आपकी संरचना के लिए सामान्य रूप से समझ में नहीं आता है, तो दूसरा समाधान बेहतर है।

+0

+1 लेकिन कृपया इसका एक उदाहरण प्रदान करें :) धन्यवाद –

+0

इसके साथ समस्या यह है कि अब आपके पास एक ऑपरेटर + है जो आपके कोडबेस में दिखाई देता है, लेकिन केवल इस विशिष्ट संदर्भ में समझ में आता है। किसी को भी कोड पढ़ने (या बनाए रखने) को भ्रमित कर सकते हैं। – jalf

+0

@jalf - शायद, लेकिन शायद नहीं। यह वास्तव में और अधिक स्थानों में समझ में आता है, मुझे नहीं पता। यदि ऐसा नहीं होता है, तो यह एक वैध कारण है कि इस पथ को न चुनें। –

1

आपको यहां से 'MULT गणना * VAL' 'जोड़ी की दूसरी ले' कार्यक्षमता अलग कर सकते हैं और 'एक संचायक के लिए कुछ जोड़ें'।

हालांकि आप यह करने के लिए बढ़ावा देने की जरूरत नहीं है, वे पहले से ही एक 'कार्यात्मक' प्रोग्रामिंग ढांचे के एक महान सौदा बनाया। यदि आप बूस्ट का उपयोग नहीं कर सकते हैं, तो आपको अपने स्वयं के कुछ टेम्पलेट जादू की आवश्यकता है। भी जटिल नहीं है, हालांकि।

#include <map> 
#include <algorithm> 
#include <numeric> 
#include <functional> 
#include <iostream> 

अब मैं इसे बेहतर वर्ग के भीतर गुणा डाल करने के लिए समझना।

// a 'take-second' functor 
template< typename at_pair > 
struct to_second_t : public std::unary_function< at_pair, typename at_pair::second_type > { 
    const typename at_pair::second_type& operator()(const at_pair & p) const { 
    return p.second; 
    } 
}; 

यह मुश्किल लग रहा है, लेकिन केवल कहने का एक सामान्य तरीका है::

struct SMyStruct 
{ 
    int MULT; 
    int VAL; 
    long f() const { return MULT*VAL; } 
}; 

'जोड़ी की दूसरी ले' के लिए एक सामान्य functor बनाएँ 'पहले ऐसा करते हैं, तो परिणाम के साथ कि ':

// compose two functors (simplified) 
template< typename at_F, typename at_G > 
struct compose_t : public std::unary_function< typename at_F::argument_type, typename at_G::result_type >{ 
    at_F f; 
    at_G g; 
    compose_t(at_F& f, at_G& g): f(f), g(g) {} 

    typename at_G::result_type operator()(const typename at_F::argument_type& v) const { 
     return g(f(v)); 
    } 
}; 

template< typename at_F, typename at_G > 
compose_t<at_F, at_G> compose(at_F& f, at_G& g) { return compose_t<at_F,at_G>(f, g); } 



// compose two functors (a unary one, and a binary one) 
// 
template< typename at_F, typename at_G > 
struct compose2_t : public std::binary_function< typename at_F::first_argument_type, typename at_G::argument_type, typename at_G::result_type >{ 
    at_F f; 
    at_G g; 
    compose2_t(at_F& f, at_G& g): f(f), g(g) {} 

    typename at_G::result_type operator()(const typename at_F::first_argument_type& a1, const typename at_G::argument_type& v) const { 
     return f(a1, g(v)); 
    } 
}; 

template< typename at_F, typename at_G > 
compose2_t<at_F, at_G> compose2(at_F& f, at_G& g) { return compose2_t<at_F,at_G>(f, g); } 

और अंत में, यह सब व्यवहार में डाल:

int main() 
{ 
    typedef std::map<int, SMyStruct > tMap; 
    tMap m; 
    SMyStruct s = {1,2}; 
    m[1].VAL = 1; m[1].MULT = 3; 
    m[2].VAL = 2; m[2].MULT = 10; 
    m[3].VAL = 3; m[3].MULT = 2; 

    // mind, this is not LISP (yet) 
    long total = std::accumulate(m.begin(), m.end(), 0, 
    compose2( 
     std::plus<int>(), 
     compose( 
     to_second_t<tMap::value_type>(), 
     std::mem_fun_ref(&SMyStruct::f))) 
    ); 

    std::cout << "total: " << total <<std::endl; 
    return 0; 
} 
संबंधित मुद्दे