Skip to content
Snippets Groups Projects
Commit 399809ed authored by Jan Trávníček's avatar Jan Trávníček
Browse files

iterator over tuple of iterators

parent 8221233b
No related branches found
No related tags found
No related merge requests found
...@@ -10,116 +10,118 @@ ...@@ -10,116 +10,118 @@
   
namespace std { namespace std {
   
template <class Iterator1, class Iterator2> template < class ... Iterators >
class const_pair_foreach_iterator { class const_tuple_foreach_iterator {
Iterator1 current1; std::tuple < Iterators ... > current;
Iterator2 current2;
   
public: template < size_t ... I >
typedef Iterator1 iterator_type1; std::tuple < const typename Iterators::value_type & ... > callDerefOperator ( const std::index_sequence < I ... > & ) const {
typedef typename iterator_traits<Iterator1>::iterator_category iterator_category1; return std::tie ( * std::get < I > ( current ) ... );
typedef typename iterator_traits<Iterator1>::value_type value_type1;
typedef Iterator1 pointer1;
typedef const value_type1& reference1;
typedef Iterator2 iterator_type2;
typedef typename iterator_traits<Iterator2>::iterator_category iterator_category2;
typedef typename iterator_traits<Iterator2>::value_type value_type2;
typedef Iterator2 pointer2;
typedef const value_type2& reference2;
explicit const_pair_foreach_iterator() {
} }
   
explicit const_pair_foreach_iterator (Iterator1 it1, Iterator2 it2) : current1(it1), current2(it2) { template < size_t ... I >
void callIncOperator ( const std::index_sequence < I ... > & ) {
std::tie ( ++std::get < I > ( current ) ... );
} }
   
const_pair_foreach_iterator (const const_pair_foreach_iterator<Iterator1, Iterator2>& it) : current1(it.current1), current2(it.current2) { template < size_t ... I >
void callDecOperator ( const std::index_sequence < I ... > & ) {
std::tie ( --std::get < I > ( current ) ... );
} }
   
const_pair_foreach_iterator& operator= (const const_pair_foreach_iterator<Iterator1, Iterator2>& it) { public:
current1 = it.current1; explicit const_tuple_foreach_iterator ( ) {
current2 = it.current2;
} }
   
iterator_type1 base1() const { explicit const_tuple_foreach_iterator ( Iterators ... it ) : current ( it ... ) {
return current1;
} }
   
iterator_type2 base2() const { template < int number >
return current2; decltype ( std::get < number > ( current ) )base ( ) const {
return std::get < number > ( current );
} }
   
std::tuple<reference1, reference2> operator*() const { template < size_t ... I >
return std::tie(*current1, *current2); std::tuple < const typename Iterators::value_type & ... > operator *( ) const {
return callDerefOperator ( std::index_sequence_for < Iterators ... > { } );
} }
   
const_pair_foreach_iterator& operator++() { template < size_t ... I >
++current1; const_tuple_foreach_iterator & operator ++( ) {
++current2; callIncOperator ( std::index_sequence_for < Iterators ... > { } );
return *this; return * this;
} }
   
const_pair_foreach_iterator& operator--() { template < size_t ... I >
--current1; const_tuple_foreach_iterator & operator --( ) {
--current2; callDecOperator ( std::index_sequence_for < Iterators ... > { } );
return *this; return * this;
} }
   
const_pair_foreach_iterator operator++(int) { const_tuple_foreach_iterator operator ++( int ) {
const_pair_foreach_iterator temp = *this; const_tuple_foreach_iterator temp = * this;
++current1;
++current2; ++( * this );
return temp; return temp;
} }
   
const_pair_foreach_iterator operator--(int) { const_tuple_foreach_iterator operator --( int ) {
const_pair_foreach_iterator temp = *this; const_tuple_foreach_iterator temp = * this;
--current1;
--current2; --( * this );
return temp; return temp;
} }
   
bool operator== (const const_pair_foreach_iterator<Iterator1, Iterator2>& other) { bool operator ==( const const_tuple_foreach_iterator < Iterators ... > & other ) {
return this->current1 == other.current1 && this->current2 == other.current2; return this->current == other.current;
} }
   
bool operator!= (const const_pair_foreach_iterator<Iterator1, Iterator2>& other) { bool operator !=( const const_tuple_foreach_iterator < Iterators ... > & other ) {
return ! ( *this == other ); return !( * this == other );
} }
   
}; };
   
template<class Iterator1, class Iterator2> template < class ... Iterators >
const_pair_foreach_iterator<Iterator1, Iterator2> make_pair_foreach_iterator (Iterator1 it1, Iterator2 it2) { const_tuple_foreach_iterator < Iterators ... > make_tuple_foreach_iterator ( Iterators ... its ) {
return const_pair_foreach_iterator<Iterator1, Iterator2>(it1, it2); return const_tuple_foreach_iterator < Iterators ... > ( its ... );
} }
   
template<class T, class R> template < class ... Types >
class const_pair_foreach { class const_tuple_foreach {
   
const T& first; const std::tuple < const Types & ... > data;
const R& second;
template < size_t ... I >
const_tuple_foreach_iterator < typename Types::const_iterator ... > callBegin ( const std::index_sequence < I ... > & ) const {
return make_tuple_foreach_iterator ( std::get < I > ( data ).cbegin ( ) ... );
}
template < size_t ... I >
const_tuple_foreach_iterator < typename Types::const_iterator ... > callEnd ( const std::index_sequence < I ... > & ) const {
return make_tuple_foreach_iterator ( std::get < I > ( data ).cend ( ) ... );
}
   
public: public:
const_pair_foreach(const T& first, const R& second) : first(first), second(second) {} const_tuple_foreach ( const Types & ... args ) : data ( args ... ) { }
   
const_pair_foreach_iterator<typename T::const_iterator, typename R::const_iterator> begin() const { template < int ... I >
return make_pair_foreach_iterator(first.begin(), second.begin()); const_tuple_foreach_iterator < typename Types::const_iterator ... > begin ( ) const {
return callBegin ( std::index_sequence_for < Types ... > { } );
} }
   
const_pair_foreach_iterator<typename T::const_iterator, typename R::const_iterator> end() const { template < int ... I >
return make_pair_foreach_iterator(first.end(), second.end()); const_tuple_foreach_iterator < typename Types::const_iterator ... > end ( ) const {
return callEnd ( std::index_sequence_for < Types ... > { } );
} }
   
}; };
   
template<class T, class R> template < class ... Types >
const_pair_foreach<T, R> make_pair_foreach(const T& first, const R& second) { const_tuple_foreach < Types ... > make_tuple_foreach ( const Types & ... args ) {
return const_pair_foreach<T, R>(first, second); return const_tuple_foreach < Types ... > ( args ... );
} }
   
} /* namespace std */ } /* namespace std */
   
#endif /* __FOREACH_HPP_ */ #endif /* __FOREACH_HPP_ */
/*
* utility.hpp
*
* Created on: Apr 7, 2016
* Author: Jan Travnicek
*/
#ifndef __UTILITY_HPP_
#define __UTILITY_HPP_
namespace std {
// TODO remove after switching to c++14
template < size_t ... I >
struct index_sequence {
typedef index_sequence < I ... > type;
};
template < size_t N, size_t ... I >
struct make_index_sequence_helper : make_index_sequence_helper < N - 1, N - 1, I ... > {
};
template < size_t ... I >
struct make_index_sequence_helper < 0, I ... > {
typedef index_sequence < I ... > type;
};
template < size_t N >
struct make_index_sequence : make_index_sequence_helper < N >::type {
};
template < typename ... T >
struct index_sequence_for : make_index_sequence < sizeof ... ( T ) > {
};
} /* namespace std */
#endif /* __UTILITY_HPP_ */
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define __FOREACH_HEADER_WRAPPER_ #define __FOREACH_HEADER_WRAPPER_
   
#include "tuple" #include "tuple"
#include "utility"
#include "extensions/foreach.hpp" #include "extensions/foreach.hpp"
   
#endif /* __FOREACH_HEADER_WRAPPER_ */ #endif /* __FOREACH_HEADER_WRAPPER_ */
......
#ifndef __UTILITY_HEADER_WRAPPER_
#define __UTILITY_HEADER_WRAPPER_
#include <bits/../utility>
#include <cstddef>
#include "extensions/utility.hpp"
#endif /* __UTILITY_HEADER_WRAPPER_ */
...@@ -15,13 +15,27 @@ void ForeachTest::tearDown() { ...@@ -15,13 +15,27 @@ void ForeachTest::tearDown() {
   
void ForeachTest::testForeach() { void ForeachTest::testForeach() {
std::vector<int> vector1 {1, 2, 3}; std::vector<int> vector1 {1, 2, 3};
std::list<int> vector2 {2, 3, 4}; std::list<int> list1 {2, 3, 4};
   
int i = 1; int i = 1;
for(const std::tuple<const int&, const int&>& elements : std::make_pair_foreach(vector1, vector2)) { for(const std::tuple<const int&, const int&>& elements : std::make_tuple_foreach(vector1, list1)) {
CPPUNIT_ASSERT(std::get<0>(elements) == i); CPPUNIT_ASSERT(std::get<0>(elements) == i);
CPPUNIT_ASSERT(std::get<1>(elements) == i + 1); CPPUNIT_ASSERT(std::get<1>(elements) == i + 1);
i++; i++;
} }
} }
   
void ForeachTest::testForeach2() {
std::vector<int> vector1 {1, 2, 3};
std::list<int> list1 {2, 3, 4};
std::set<int> set1 {3, 4, 5};
int i = 1;
for(const std::tuple<const int&, const int&, const int&>& elements : std::make_tuple_foreach(vector1, list1, set1)) {
CPPUNIT_ASSERT(std::get<0>(elements) == i);
CPPUNIT_ASSERT(std::get<1>(elements) == i + 1);
CPPUNIT_ASSERT(std::get<2>(elements) == i + 2);
i++;
}
}
...@@ -7,6 +7,7 @@ class ForeachTest : public CppUnit::TestFixture ...@@ -7,6 +7,7 @@ class ForeachTest : public CppUnit::TestFixture
{ {
CPPUNIT_TEST_SUITE( ForeachTest ); CPPUNIT_TEST_SUITE( ForeachTest );
CPPUNIT_TEST( testForeach ); CPPUNIT_TEST( testForeach );
CPPUNIT_TEST( testForeach2 );
CPPUNIT_TEST_SUITE_END(); CPPUNIT_TEST_SUITE_END();
   
public: public:
...@@ -14,6 +15,7 @@ public: ...@@ -14,6 +15,7 @@ public:
void tearDown(); void tearDown();
   
void testForeach(); void testForeach();
void testForeach2();
}; };
   
#endif // COMPARE_TEST_H_ #endif // COMPARE_TEST_H_
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment