Ok, vì vậy đây không phải là giải pháp đầy đủ - nhưng tôi hết thời gian. Vì vậy, điều này hiện đang thực hiện không phải là một iterator đầy đủ nhưng một lớp học giảm giống như iterator mà định nghĩa một cái gì đó giống như giao diện này, và yêu cầu C + + 11. Tôi đã thử nghiệm nó trên g ++ 4.7:
template<typename NestedContainerType, typename Terminator>
class flatten_iterator
{
bool complete();
void advance();
Terminator& current();
};
đâu NestedContainerType
là loại chứa lồng nhau (ngạc nhiên), và Terminator là loại điều sâu thẳm nhất mà bạn đang mong muốn có được ra khỏi flatten.
Mã bên dưới hoạt động, nhưng điều này chắc chắn không được thử nghiệm rộng rãi. Gói nó lên đầy đủ (giả sử bạn đang hạnh phúc với tiến lên phía trước chỉ) không nên quá nhiều công việc, đặc biệt nếu bạn sử dụng boost::iterator_facade
.
#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;
};
Và với trường hợp kiểm tra sau, nó làm những gì bạn mong đợi:
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();
}
}
Vì vậy, in ra sau cho mỗi người trong số các loại container:
1
2
3
4
Lưu ý rằng nó doesn chưa làm việc với set
s vì có một số foo cần thiết để đối phó với thực tế là các trình lặp vòng set
trả về tham chiếu const. Tập thể dục cho người đọc ... :-)
wow. có vẻ tốt, công trình, rất gần với những gì tôi cần. Một nhận xét: Tôi cố gắng sử dụng ít thư viện khi cần thiết. Vì vậy, là 'boost :: scoped_ptr' thực sự cần thiết? – steffen
'scoped_ptr' hoàn toàn không cần thiết. Chỉ lưu trữ trình vòng lặp theo giá trị. –
??? Tôi đoán tôi đang tạo ra một sai lầm ngu ngốc, nhưng dòng 'typename inner_it_type m_inner_it;' cung cấp cho trình biên dịch lỗi 'dự kiến nested-name-specifier trước 'inner_it_type'' – steffen