मैंने महसूस किया कि यहाँ कोई भी उत्तर यह नहीं समझाता है कि क्यों मैं कंटेनरों में अनुक्रमण के बारे में एक सामान्य अवधारणा के रूप में पुनरावृत्तियों को पसंद करता हूं। ध्यान दें कि पुनरावृत्तियों का उपयोग करने का मेरा अधिकांश अनुभव वास्तव में C ++ से नहीं, बल्कि पायथन जैसी उच्च-स्तरीय प्रोग्रामिंग भाषाओं से आता है।
इट्रेटर इंटरफ़ेस आपके फ़ंक्शन के उपभोक्ताओं पर कम आवश्यकताओं को लागू करता है, जो उपभोक्ताओं को इसके साथ और अधिक करने की अनुमति देता है।
यदि आप सभी की जरूरत है कि आगे-आगे चलने में सक्षम हो, तो डेवलपर अनुक्रमित कंटेनरों का उपयोग करने के लिए सीमित नहीं है - वे किसी भी वर्ग के कार्यान्वयन का उपयोग कर सकते हैं operator++(T&)
, operator*(T)
और operator!=(const &T, const &T)
।
#include <iostream>
template <class InputIterator>
void printAll(InputIterator& begin, InputIterator& end)
{
for (auto current = begin; current != end; ++current) {
std::cout << *current << "\n";
}
}
// elsewhere...
printAll(myVector.begin(), myVector.end());
आपका एल्गोरिथ्म उस मामले के लिए काम करता है जिसकी आपको आवश्यकता है - एक वेक्टर पर पुनरावृत्ति - लेकिन यह उन अनुप्रयोगों के लिए भी उपयोगी हो सकता है जिन्हें आप जरूरी नहीं समझते हैं:
#include <random>
class RandomIterator
{
private:
std::mt19937 random;
std::uint_fast32_t current;
std::uint_fast32_t floor;
std::uint_fast32_t ceil;
public:
RandomIterator(
std::uint_fast32_t floor = 0,
std::uint_fast32_t ceil = UINT_FAST32_MAX,
std::uint_fast32_t seed = std::mt19937::default_seed
) :
floor(floor),
ceil(ceil)
{
random.seed(seed);
++(*this);
}
RandomIterator& operator++()
{
current = floor + (random() % (ceil - floor));
}
std::uint_fast32_t operator*() const
{
return current;
}
bool operator!=(const RandomIterator &that) const
{
return current != that.current;
}
};
int main()
{
// roll a 1d6 until we get a 6 and print the results
RandomIterator firstRandom(1, 7, std::random_device()());
RandomIterator secondRandom(6, 7);
printAll(firstRandom, secondRandom);
return 0;
}
एक वर्ग-ब्रैकेट ऑपरेटर को लागू करने का प्रयास करना जो इस पुनरावृत्ति के समान कुछ करता है, को वंचित किया जाएगा, जबकि पुनरावृत्त कार्यान्वयन अपेक्षाकृत सरल है। स्क्वायर-ब्रैकेट्स ऑपरेटर आपकी कक्षा की क्षमताओं के बारे में भी निहितार्थ बनाता है - जिसे आप किसी भी मनमाने बिंदु पर अनुक्रमित कर सकते हैं - जिसे लागू करना मुश्किल या अक्षम हो सकता है।
Iterators भी खुद को सजावट के लिए उधार देते हैं । लोग पुनरावृत्तियों को लिख सकते हैं जो अपने निर्माता में एक पुनरावृत्ति लेते हैं और इसकी कार्यक्षमता बढ़ाते हैं:
template<class InputIterator, typename T>
class FilterIterator
{
private:
InputIterator internalIterator;
public:
FilterIterator(const InputIterator &iterator):
internalIterator(iterator)
{
}
virtual bool condition(T) = 0;
FilterIterator<InputIterator, T>& operator++()
{
do {
++(internalIterator);
} while (!condition(*internalIterator));
return *this;
}
T operator*()
{
// Needed for the first result
if (!condition(*internalIterator))
++(*this);
return *internalIterator;
}
virtual bool operator!=(const FilterIterator& that) const
{
return internalIterator != that.internalIterator;
}
};
template <class InputIterator>
class EvenIterator : public FilterIterator<InputIterator, std::uint_fast32_t>
{
public:
EvenIterator(const InputIterator &internalIterator) :
FilterIterator<InputIterator, std::uint_fast32_t>(internalIterator)
{
}
bool condition(std::uint_fast32_t n)
{
return !(n % 2);
}
};
int main()
{
// Rolls a d20 until a 20 is rolled and discards odd rolls
EvenIterator<RandomIterator> firstRandom(RandomIterator(1, 21, std::random_device()()));
EvenIterator<RandomIterator> secondRandom(RandomIterator(20, 21));
printAll(firstRandom, secondRandom);
return 0;
}
हालांकि ये खिलौने सांसारिक लग सकते हैं, एक साधारण इंटरफ़ेस के साथ शक्तिशाली चीजें करने के लिए पुनरावृत्तियों और पुनरावृत्त डेकोरेटर का उपयोग करने की कल्पना करना मुश्किल नहीं है - डेटाबेस के फॉरवर्ड-इट्रेटर के इट्रेटर के साथ केवल एक परिणाम से एक मॉडल ऑब्जेक्ट का निर्माण करना । ये पैटर्न अनंत सेट की स्मृति-कुशल पुनरावृत्ति को सक्षम करते हैं और, जैसा कि मैंने ऊपर लिखा एक फिल्टर के साथ, परिणामों का संभावित आलसी मूल्यांकन।
C ++ टेम्प्लेट की शक्ति का एक हिस्सा आपका इटरेटर इंटरफ़ेस है, जब फिक्स्ड-लेंथ सी सरणियों की पसंद पर लागू किया जाता है, सरल और कुशल पॉइंटर अंकगणित के लिए लागू होता है , जिससे यह वास्तव में शून्य-लागत अमूर्त होता है।
some_iterator++
कर रहे हैं++some_iterator
। पोस्ट-इन्क्रीमेंट एक अनावश्यक अस्थायी पुनरावृत्ति बनाता है।