2012-03-29 15 views
12

में प्रत्येक संरचना से एक एकल सदस्य का चयन करने के लिए मेरे पास एक विजुअल स्टूडियो 2008 सी ++ प्रोजेक्ट है जहां मैं उस संरचना प्रकार के वेक्टर के एक संरचना तत्व को एक नए वेक्टर में कॉपी करना चाहता हूं। उदाहरण के लिए:किसी अन्य वेक्टर

struct Foo { 
    int a; 
    long b; 
}; 

std::vector<Foo> v1; 
std::vector<long> v2; 

for(std::vector<Foo>::const_iterator it = v1.begin(); it != v1.end(); ++it) 
{ 
    v2.push_back(it->b); 
} 

क्या इससे बेहतर/अधिक सुरुचिपूर्ण तरीका है?

धन्यवाद, PaulH

उत्तर

16

दृश्य C++ 2008, नहीं, इस के रूप में "सुरुचिपूर्ण" के रूप में यह हो जाता है के बारे में है। मानक लाइब्रेरी एल्गोरिदम प्रदान करती है जिसका उपयोग कंटेनरों में हेरफेर करने के लिए किया जा सकता है, लेकिन ज्यादातर परिदृश्यों में - विशेष रूप से इस तरह के सरल उपयोग मामलों में - वे उपयोग करने के लिए बहुत बोझिल हैं।

सी ++ 11 सी ++ में लैम्ब्डा अभिव्यक्ति जोड़ता है। विजुअल सी ++ 2010 और अन्य सी ++ कंपाइलर्स के हाल के संस्करण इस सी ++ 11 फीचर का समर्थन करते हैं। लैम्ब्डा भाव के साथ, आप आसानी से अपने कार्य के लिए transform एल्गोरिथ्म का उपयोग कर सकते हैं:

std::transform(v1.begin(), v1.end(), std::back_inserter(v2), 
       [](Foo const& x) { return x.b; }); 

लैम्ब्डा भाव के बिना, आप struct से b तत्व को निकालने के लिए एक समारोह को परिभाषित करना होगा:

long get_b(Foo const& x) { return x.b; } 

इसके बाद आप transform एल्गोरिथ्म के साथ इस समारोह का उपयोग कर सकता:

std::transform(v1.begin(), v1.end(), std::back_inserter(v2), get_b); 

हालांकि, इस तरह सरल उपयोग के मामलों के लिए, इस qu कर सकते हैं अजीब कोड को अजीब तरह से ले जाता है क्योंकि सभी संबंधित कार्यों को अच्छी तरह से रखना मुश्किल है।

+0

और, ज़ाहिर है, बूस्ट.लैम्ब्डा जैसी अन्य तकनीकें हैं, या सामान्य उद्देश्य ट्रांसफॉर्मर लिख रही हैं और मानक लाइब्रेरी बाइंडर्स के साथ उनका उपयोग कर रही हैं, लेकिन इन तकनीकों में से कोई भी मूल कोड में क्या नहीं है । –

+2

मुझे लगता है कि हस्ताक्षर 'लंबा और (फू एंड)' का एक कार्य प्राप्त करने के लिए आप 'std :: bind (& foo :: b)' का उपयोग भी कर सकते हैं। –

+0

मैंने अपनी याददाश्त से 'बांध' को पूरी तरह से अवरुद्ध करने की कोशिश की है, हालांकि मुझे डर है कि कुछ निशान हमेशा के लिए बने रहेंगे। : -ओ –

1

यह वास्तव में "बेहतर" के साथ आपका क्या मतलब है इस पर निर्भर करता है।

तो तुम्हारा मतलब अगर एक ही टेम्पलेट प्रवंचना का उपयोग करके लिखा जा सकता है तो जवाब है हां:

template<typename C, typename T> 
struct MemberGetter 
{ 
    T C::*mp; 
    MemberGetter(T C::*mp) : mp(mp) { } 
    T operator()(const C& c) { return c.*mp; } 
}; 

struct Foo 
{ 
    double dm; 
}; 

... 
std::vector<double> x; 
std::vector<Foo> y; 

std::transform(y.begin(), y.end(), 
       std::back_inserter(x), 
       MemberGetter<Foo, double>(&Foo::dm)); 

यह मेरी राय में कोई स्पष्ट पाश से भी बदतर है, लेकिन लाभ यह है कि सदस्य सूचक है (यानी आप जिस संरचना की प्रतिलिपि बना रहे हैं उसका एक हिस्सा) रनटाइम पैरामीटर हो सकता है।

यदि सदस्य को कॉपी करने की आवश्यकता है तो उसे जाना जाता है और तय किया जाता है तो मैं कहूंगा कि स्पष्ट लूप सबसे अच्छा तरीका है (मैं मुश्किल से कल्पना कर सकता हूं जिसमें एक समान टेम्पलेट का उपयोग किया जाता है जहां सदस्य सूचक टेम्पलेट पैरामीटर होता है कोई समझ में आता है)।

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