(::) std :: map के साथ रेंज-आधारित () लूप का उपयोग कैसे करें?


336

(+) छोरों के लिए C ++ 11 रेंज-आधारित के लिए सामान्य उदाहरण हमेशा कुछ इस तरह सरल होता है:

std::vector<int> numbers = { 1, 2, 3, 4, 5, 6, 7 };
for ( auto xyz : numbers )
{
     std::cout << xyz << std::endl;
}

जिस मामले xyzमें ए int। लेकिन, क्या होता है जब हमारे पास नक्शे जैसा कुछ होता है? इस उदाहरण में चर का प्रकार क्या है:

std::map< foo, bar > testing = { /*...blah...*/ };
for ( auto abc : testing )
{
    std::cout << abc << std::endl;         // ? should this give a foo? a bar?
    std::cout << abc->first << std::endl;  // ? or is abc an iterator?
}

जब ट्रेस किया जा रहा कंटेनर कुछ सरल होता है, तो ऐसा लगता है कि रेंज-आधारित () लूप्स हमें प्रत्येक आइटम देगा, न कि इट्रेटर। जो अच्छा है ... अगर यह पुनरावृत्त था, तो पहली बात यह है कि हमें हमेशा ऐसा करना होगा, वैसे भी इसे रोकना होगा।

लेकिन मैं उलझन में हूं कि जब यह नक्शे और मल्टीमैप जैसी चीजों की बात करता है तो क्या करना है।

(मैं अभी भी जी ++ 4.4 पर हूं, जबकि रेंज-आधारित लूप जी ++ 4.6+ में हैं, इसलिए मुझे अभी तक प्रयास करने का मौका नहीं मिला है।)


4
बयान के लिए सीमा मानक पुस्तकालय std::beginऔर std::endएक ही नाम के तहत कार्यों या सदस्य कार्यों के साथ एक अपवित्र नृत्य करता है ।
बजे जीन बुशुइव

10
@ एक 3-लाइन उदाहरण पर, आप नकली चर नाम पर पकड़े जा रहे हैं?
स्टीफन

जवाबों:


495

कंटेनर का प्रत्येक तत्व एक है map<K, V>::value_type, जो एक के typedefलिए है std::pair<const K, V>। नतीजतन, C ++ 17 या उच्चतर में, आप लिख सकते हैं

for (auto& [key, value]: myMap) {
    std::cout << key << " has value " << value << std::endl;
}

या के रूप में

for (const auto& [key, value]: myMap) {
    std::cout << key << " has value " << value << std::endl;
}

यदि आप मूल्यों को संशोधित करने की योजना नहीं बनाते हैं।

C ++ 11 और C ++ 14 में, आप forप्रत्येक जोड़े को स्वयं निकालने के लिए एन्हांस्ड लूप का उपयोग कर सकते हैं , फिर मैन्युअल रूप से कुंजियों और मानों को निकाल सकते हैं:

for (const auto& kv : myMap) {
    std::cout << kv.first << " has value " << kv.second << std::endl;
}

यदि आप मानों का केवल-पढ़ने का दृश्य चाहते हैं, तो आप kvचर को चिह्नित करने पर भी विचार कर सकते हैं const


95

C ++ 17 में इसे संरचित बाइंडिंग कहा जाता है , जो निम्नलिखित के लिए अनुमति देता है:

std::map< foo, bar > testing = { /*...blah...*/ };
for ( const auto& [ k, v ] : testing )
{
  std::cout << k << "=" << v << "\n";
}

यह const &कुंजी के लिए एक संभव है , लेकिन मूल्य के लिए एक गैर-कास्ट संदर्भ प्राप्त करना संभव है ? (क्योंकि यह है कि क्या नक्शा :: value_type करता है ...)
peterchen

2
@peterchen: kहै constअगर आप का उपयोग करेंfor(auto&[k,v]:testing)
dalle


यदि आप जीसीसी के साथ संकलित कर रहे हैं तो आपको संरचित बाइंडिंग के लिए संस्करण 7 या बेहतर चाहिए: gcc.gnu.org/projects/cxx-status.html
csknk

25

इस पत्र से: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2049.pdf

for( type-specifier-seq simple-declarator : expression ) statement

के समतुल्य है

{
    typedef decltype(expression) C;
    auto&& rng(expression);
    for (auto begin(std::For<C>::begin(rng)), end(std::For<C>::end(rng)); begin != end; ++ begin) {
        type-specier-seq simple-declarator(*begin);
        statement
    }
}

तो आप स्पष्ट रूप से देख सकते हैं कि abcआपके मामले में क्या है std::pair<key_type, value_type >। तो मुद्रण के लिए आप प्रत्येक तत्व तक पहुँच प्राप्त कर सकते हैं abc.firstऔरabc.second


15

यदि आप केवल अपने नक्शे से कुंजियों / मूल्यों को देखना चाहते हैं और बूस्ट का उपयोग करना चाहते हैं, तो आप सीमा आधारित लूप के साथ बूस्टर एडेप्टर का उपयोग कर सकते हैं:

for (const auto& value : myMap | boost::adaptors::map_values)
{
    std::cout << value << std::endl;
}

एक समान बढ़ावा है :: एडेप्टर :: key_values

http://www.boost.org/doc/libs/1_51_0/libs/range/doc/html/range/reference/adaptors/reference/map_values.html


3

अगर foo और bar का कॉपी असाइनमेंट ऑपरेटर सस्ता है (जैसे। int, char, pointer etc), तो आप निम्न कार्य कर सकते हैं:

foo f; bar b;
BOOST_FOREACH(boost::tie(f,b),testing)
{
  cout << "Foo is " << f << " Bar is " << b;
}

4
कोड का पहला स्निपेट "C ++ 11 श्रेणी-आधारित ()" का उपयोग नहीं कर रहा है। यह "सी ++ 11: उत्तर का उपयोग करने के लिए कैसे () एसटीडी के साथ लूप के लिए जवाब नहीं है: नक्शा?"
isoiphone

1
@ytj यह पहले से ही जवाब में उल्लेख किया गया है कि यह काम नहीं करता है। मैं इसे हटाना नहीं चाहता ताकि नए उपयोगकर्ताओं को इसे आज़माने की जरूरत न पड़े और इस तथ्य को फिर से पता चले।
बाल्की जूल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.