ठीक है, तो यह एक पूर्ण समाधान नहीं है - लेकिन मैं समय से बाहर भाग गया। तो यह वर्तमान में पूर्ण इटरेटर नहीं लागू करता है लेकिन इटरेटर जैसी कक्षा को काटता है जो इस इंटरफेस की तरह कुछ परिभाषित करता है, और सी ++ 11 की आवश्यकता होती है। मैं जी ++ 4.7 पर जाँच की है:
template<typename NestedContainerType, typename Terminator>
class flatten_iterator
{
bool complete();
void advance();
Terminator& current();
};
कहाँ NestedContainerType
नेस्टेड कंटेनर प्रकार (आश्चर्यजनक) है, और टर्मिनेटर अंतरतम बात यह है कि आप समतल से बाहर निकलने के लिए इच्छुक रहे हैं के प्रकार है।
नीचे दिया गया कोड काम करता है, लेकिन यह निश्चित रूप से व्यापक रूप से परीक्षण नहीं किया जाता है। इसे पूरी तरह से लपेटना (माना जाता है कि आप केवल अग्रिम अग्रिम के साथ खुश हैं) विशेष रूप से यदि आप boost::iterator_facade
का उपयोग करते हैं तो बहुत अधिक काम नहीं होना चाहिए।
1
2
3
4
ध्यान दें कि यह नहीं करता है:
int main(int argc, char* argv[])
{
typedef std::vector<int> n1_t;
typedef std::vector<std::deque<short> > n2_t;
typedef std::list<std::vector<std::vector<std::vector<double> > > > n4_t;
typedef std::vector<std::deque<std::vector<std::deque<std::vector<std::list<float> > > > > > n6_t;
n1_t n1 = { 1, 2, 3, 4 };
n2_t n2 = { {}, { 1, 2 }, {3}, {}, {4}, {}, {} };
n4_t n4 = { { { {1.0}, {}, {}, {2.0}, {} }, { {}, {} }, { {3.0} } }, { { { 4.0 } } } };
n6_t n6 = { { { { { {1.0f}, {}, {}, {2.0f}, {} }, { {}, {} }, { {3.0f} } }, { { { 4.0f } } } } } };
flatten_iterator<n1_t, int> i1(n1);
while (!i1.complete())
{
std::cout << i1.current() << std::endl;
i1.advance();
}
flatten_iterator<n2_t, short> i2(n2);
while (!i2.complete())
{
std::cout << i2.current() << std::endl;
i2.advance();
}
flatten_iterator<n4_t, double> i4(n4);
while (!i4.complete())
{
std::cout << i4.current() << std::endl;
i4.advance();
}
flatten_iterator<n6_t, float> i6(n6);
while (!i6.complete())
{
std::cout << i6.current() << std::endl;
i6.advance();
}
}
तो कंटेनर प्रकारों में से प्रत्येक के लिए निम्नलिखित प्रिंट:
#include <list>
#include <deque>
#include <vector>
#include <iostream>
template<typename ContainerType, typename Terminator>
class flatten_iterator
{
public:
typedef flatten_iterator<typename ContainerType::value_type, Terminator> inner_it_type;
typedef typename inner_it_type::value_type value_type;
public:
flatten_iterator() {}
flatten_iterator(ContainerType& container) : m_it(container.begin()), m_end(container.end())
{
skipEmpties();
}
bool complete()
{
return m_it == m_end;
}
value_type& current()
{
return m_inner_it.current();
}
void advance()
{
if (!m_inner_it.complete())
{
m_inner_it.advance();
}
if (m_inner_it.complete())
{
++m_it;
skipEmpties();
}
}
private:
void skipEmpties()
{
while (!complete())
{
m_inner_it = inner_it_type(*m_it);
if (!m_inner_it.complete()) break;
++m_it;
}
}
private:
inner_it_type m_inner_it;
typename ContainerType::iterator m_it, m_end;
};
template<template<typename, typename ...> class ContainerType, typename Terminator, typename ... Args>
class flatten_iterator<ContainerType<Terminator, Args...>, Terminator>
{
public:
typedef typename ContainerType<Terminator, Args...>::value_type value_type;
public:
flatten_iterator() {}
flatten_iterator(ContainerType<Terminator, Args...>& container) :
m_it(container.begin()), m_end(container.end())
{
}
bool complete()
{
return m_it == m_end;
}
value_type& current() { return *m_it; }
void advance() { ++m_it; }
private:
typename ContainerType<Terminator, Args...>::iterator m_it, m_end;
};
और निम्न परीक्षण मामलों के साथ, यह आप क्या उम्मीद करेंगे करता है set
एस के साथ अभी तक काम नहीं कर रहा है क्योंकि इस तथ्य से निपटने के लिए कुछ फू आवश्यक है कि set
इटरेटर्स रिटर्न कॉन्स्ट्रेंस संदर्भ। पाठक के लिए व्यायाम ... :-)
वाह। अच्छा लग रहा है, काम करता है, मुझे जो चाहिए वह बहुत करीब है। एक टिप्पणी: मैं आवश्यकतानुसार छोटी पुस्तकालयों के रूप में उपयोग करने की कोशिश करता हूं। तो क्या 'boost :: scoped_ptr' वास्तव में आवश्यक है? – steffen
'scoped_ptr' पूरी तरह से आवश्यक नहीं है। बस इटरेटर को मूल्य से स्टोर करें। –
??? मुझे लगता है कि मैं एक बेवकूफ गलती कर रहा हूं, लेकिन लाइन 'typename inner_it_type m_inner_it' 'कंपाइलर त्रुटि' को 'आंतरिक_ट_टाइप' – steffen