#include <iterator>
#include <algorithm>
typedef int Foo;
struct Bar
{
int start;
int stop;
Bar(int start, int stop) : start(start), stop(stop) {}
size_t size_foo() const {return size_t(stop-start);}
//shameful memory leak, but just a silly example:
Foo& get_foo(size_t index) const {return *new int(start+index);}
};
// incomplete general case
template <typename TOuter> struct LegacyContainerTraits;
// Specialization for 'Bar'
template <> struct LegacyContainerTraits<Bar>
{
// The inner type of 'Bar' is 'Foo'
typedef Foo inner_type;
static size_t get_size(Bar const& outer) {
return outer.size_foo();
}
static Foo& get_element(Bar const& outer, size_t index) {
return outer.get_foo(index);
}
};
template <typename TOuter> class LegacyContainerIterator;
template <typename TOuter> LegacyContainerIterator<TOuter> begin(TOuter& );
template <typename TOuter> LegacyContainerIterator<TOuter> end(TOuter& );
template <typename TOuter>
class LegacyContainerIterator :
public std::iterator<std::random_access_iterator_tag,
typename LegacyContainerTraits<TOuter>::inner_type >
{
private:
TOuter& mContainerRef;
size_t mIndex;
friend LegacyContainerIterator<TOuter> begin<TOuter>(TOuter& );
friend LegacyContainerIterator<TOuter> end<TOuter>(TOuter& );
LegacyContainerIterator(TOuter& containerRef, size_t index) :
mContainerRef(containerRef), mIndex(index)
{}
public:
typedef std::iterator<std::random_access_iterator_tag,
typename LegacyContainerTraits<TOuter>::inner_type > baseclass;
using typename baseclass::reference;
using typename baseclass::difference_type;
using typename baseclass::pointer;
using typename baseclass::value_type;
using typename baseclass::iterator_category;
// usual suspect operators
typename baseclass::reference operator*() {
return LegacyContainerTraits<TOuter>
::get_element(mContainerRef, mIndex);
}
bool operator==(LegacyContainerIterator<TOuter> const& rhs) const
{
return &mContainerRef == &rhs.mContainerRef &&
mIndex == rhs.mIndex;
}
bool operator!=(LegacyContainerIterator<TOuter> const& rhs) const
{
return !operator==(rhs);
}
LegacyContainerIterator const& operator++()
{
++mIndex;
return *this;
}
};
template <typename TOuter>
LegacyContainerIterator<TOuter> begin(TOuter& containerRef)
{
return LegacyContainerIterator<TOuter>(containerRef, 0);
}
template <typename TOuter>
LegacyContainerIterator<TOuter> end(TOuter& containerRef)
{
return LegacyContainerIterator<TOuter>(
containerRef,
LegacyContainerTraits<TOuter>::get_size(containerRef));
}
#include <iostream>
int main()
{
Bar b(10, 20);
for (auto it=begin(b); it!=end(b); ++it)
{
std::cout<<*it<<std::endl;
}
std::for_each(begin(b), end(b), [](Foo& f){std::cout<<"Foo: "<<f<<std::endl;});
// GCC doesn't have range-based for yet?
//for (auto it : b)
//{
// std::cout<<*it<<std::endl;
//}
}