fork download
  1. #include <iterator>
  2. #include <algorithm>
  3.  
  4. typedef int Foo;
  5.  
  6. struct Bar
  7. {
  8. int start;
  9. int stop;
  10. Bar(int start, int stop) : start(start), stop(stop) {}
  11.  
  12. size_t size_foo() const {return size_t(stop-start);}
  13. //shameful memory leak, but just a silly example:
  14. Foo& get_foo(size_t index) const {return *new int(start+index);}
  15. };
  16.  
  17.  
  18. // incomplete general case
  19. template <typename TOuter> struct LegacyContainerTraits;
  20.  
  21. // Specialization for 'Bar'
  22. template <> struct LegacyContainerTraits<Bar>
  23. {
  24. // The inner type of 'Bar' is 'Foo'
  25. typedef Foo inner_type;
  26. static size_t get_size(Bar const& outer) {
  27. return outer.size_foo();
  28. }
  29.  
  30. static Foo& get_element(Bar const& outer, size_t index) {
  31. return outer.get_foo(index);
  32. }
  33. };
  34.  
  35. template <typename TOuter> class LegacyContainerIterator;
  36. template <typename TOuter> LegacyContainerIterator<TOuter> begin(TOuter& );
  37. template <typename TOuter> LegacyContainerIterator<TOuter> end(TOuter& );
  38.  
  39. template <typename TOuter>
  40. class LegacyContainerIterator :
  41. public std::iterator<std::random_access_iterator_tag,
  42. typename LegacyContainerTraits<TOuter>::inner_type >
  43. {
  44. private:
  45. TOuter& mContainerRef;
  46. size_t mIndex;
  47. friend LegacyContainerIterator<TOuter> begin<TOuter>(TOuter& );
  48. friend LegacyContainerIterator<TOuter> end<TOuter>(TOuter& );
  49.  
  50. LegacyContainerIterator(TOuter& containerRef, size_t index) :
  51. mContainerRef(containerRef), mIndex(index)
  52. {}
  53. public:
  54. typedef std::iterator<std::random_access_iterator_tag,
  55. typename LegacyContainerTraits<TOuter>::inner_type > baseclass;
  56. using typename baseclass::reference;
  57. using typename baseclass::difference_type;
  58. using typename baseclass::pointer;
  59. using typename baseclass::value_type;
  60. using typename baseclass::iterator_category;
  61.  
  62. // usual suspect operators
  63. typename baseclass::reference operator*() {
  64. return LegacyContainerTraits<TOuter>
  65. ::get_element(mContainerRef, mIndex);
  66. }
  67.  
  68. bool operator==(LegacyContainerIterator<TOuter> const& rhs) const
  69. {
  70. return &mContainerRef == &rhs.mContainerRef &&
  71. mIndex == rhs.mIndex;
  72. }
  73.  
  74. bool operator!=(LegacyContainerIterator<TOuter> const& rhs) const
  75. {
  76. return !operator==(rhs);
  77. }
  78.  
  79. LegacyContainerIterator const& operator++()
  80. {
  81. ++mIndex;
  82. return *this;
  83. }
  84. };
  85.  
  86. template <typename TOuter>
  87. LegacyContainerIterator<TOuter> begin(TOuter& containerRef)
  88. {
  89. return LegacyContainerIterator<TOuter>(containerRef, 0);
  90. }
  91.  
  92. template <typename TOuter>
  93. LegacyContainerIterator<TOuter> end(TOuter& containerRef)
  94. {
  95. return LegacyContainerIterator<TOuter>(
  96. containerRef,
  97. LegacyContainerTraits<TOuter>::get_size(containerRef));
  98. }
  99.  
  100. #include <iostream>
  101.  
  102. int main()
  103. {
  104. Bar b(10, 20);
  105. for (auto it=begin(b); it!=end(b); ++it)
  106. {
  107. std::cout<<*it<<std::endl;
  108. }
  109.  
  110. std::for_each(begin(b), end(b), [](Foo& f){std::cout<<"Foo: "<<f<<std::endl;});
  111.  
  112. // GCC doesn't have range-based for yet?
  113. //for (auto it : b)
  114. //{
  115. // std::cout<<*it<<std::endl;
  116. //}
  117. }
Success #stdin #stdout 0s 3060KB
stdin
Standard input is empty
stdout
10
11
12
13
14
15
16
17
18
19
Foo: 10
Foo: 11
Foo: 12
Foo: 13
Foo: 14
Foo: 15
Foo: 16
Foo: 17
Foo: 18
Foo: 19