Newer
Older
* This file is part of Algorithms library toolkit.
* Copyright (C) 2017 Jan Travnicek (jan.travnicek@fit.cvut.cz)
* Algorithms library toolkit is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* Algorithms library toolkit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with Algorithms library toolkit. If not, see <http://www.gnu.org/licenses/>.
*
* Created on: Apr 1, 2013
* Author: Jan Travnicek
*/
#ifndef __FOREACH_HPP_
#define __FOREACH_HPP_
/**
* \brief
* A class for packing a tuple of iterators and synchronizing them. All are incremented, decremented, dereferenced together.
*/
template < class ... Iterators >
class const_tuple_foreach_iterator {
/**
* The underlying pack of iterators.
*/
/**
* \brief
* Helper method to dereference all operators. The method collects the results of dereference operator on individual iterators.
*
* \tparam I ... indexes to the the iterator tuple
*
* \return a tuple of values the individual iterators refer to
*/
ext::tuple < const typename Iterators::value_type & ... > callDerefOperator ( const std::index_sequence < I ... > & ) const {
return ext::tie ( * std::get < I > ( current ) ... );
* Helper method to increment all underlying iterators.
*/
template < size_t ... I >
void callIncOperator ( const std::index_sequence < I ... > & ) {
ext::tie ( ++std::get < I > ( current ) ... );
* Helper method to decrement all underlying iterators.
*/
template < size_t ... I >
void callDecOperator ( const std::index_sequence < I ... > & ) {
ext::tie ( --std::get < I > ( current ) ... );
/**
* \brief
* Constructor of the iterator tuple from a pack of iterators.
*
* \param it ... pack of iterators
*
*/
explicit const_tuple_foreach_iterator ( Iterators ... it ) : current ( it ... ) {
/**
* \brief
* Getter of an Ith iterator from the tuple of underlying iterators.
*
* \tparam I the specification of the iterator index.
*/
template < size_t I >
decltype ( std::get < I > ( current ) ) base ( ) const {
return std::get < I > ( current );
/**
* \brief
* Implementation of dereference operator on all iterators in the tuple.
*
* \return a tuple of values the individual iterators refer to
*/
ext::tuple < const typename Iterators::value_type & ... > operator *( ) const {
return callDerefOperator ( std::index_sequence_for < Iterators ... > { } );
/**
* \brief
* Prefix version of increment operator that propagates the call to all underlying iterators.
*
* \return this
*/
const_tuple_foreach_iterator & operator ++( ) {
callIncOperator ( std::index_sequence_for < Iterators ... > { } );
return * this;
/**
* \brief
* Prefix version of decrement operator that propagates the call to all underlying iterators.
*
* \return this
*/
const_tuple_foreach_iterator & operator --( ) {
callDecOperator ( std::index_sequence_for < Iterators ... > { } );
return * this;
/**
* \brief
* Postfix version of increment operator that propagates the call to all underlying iterators.
*
* \return original value
*/
const_tuple_foreach_iterator operator ++( int ) {
const_tuple_foreach_iterator temp = * this;
++( * this );
/**
* \brief
* Postfix version of decrement operator that propagates the call to all underlying iterators.
*
* \return original value
*/
const_tuple_foreach_iterator operator --( int ) {
const_tuple_foreach_iterator temp = * this;
--( * this );
/**
* \brief
* Implementation of equality comparison operator on tuple of iterators
*
* \param other the other instance to compare with
*
* \return bool true if iterators of this class are equal to iterators of the other class
*/
bool operator ==( const const_tuple_foreach_iterator < Iterators ... > & other ) {
return this->current == other.current;
/**
* \brief
* Implementation of inequality comparison operator on tuple of iterators
*
* \param other the other instance to compare with
*
* \return bool true if iterators of this class are not equal to iterators of the other class
*/
bool operator !=( const const_tuple_foreach_iterator < Iterators ... > & other ) {
return !( * this == other );
/**
* \brief
* Function construction of the tuple iterator.
*
* \tparam Iterators ... the types of interators to pack
*
* \param its ... the actual iterators to pack
*
* \return the tuple of iterators itself mimicking the iterator interface to some level
*/
template < class ... Iterators >
const_tuple_foreach_iterator < Iterators ... > make_tuple_foreach_iterator ( Iterators ... its ) {
return const_tuple_foreach_iterator < Iterators ... > ( its ... );
/**
* \brief
* Class providing begin and end methods to allow simple use of packed iterators in foreach variant of the for loop
*
* \tparam Types ... the types of begin/end source classes
*/
template < class ... Types >
class const_tuple_foreach {
/**
* \brief
* Source classes to retrieve begin and end iterators from
*/
const ext::tuple < const Types & ... > data;
* Helper to call begin on source classes.
*
* \tparam I the specification of the iterator index
*
* \return the iterator tuple class
*/
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 ( ) ... );
}
* Helper to call end on source classes.
*
* \tparam I the specification of the iterator index
*
* \return the iterator tuple class
*/
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 ( ) ... );
}
/**
* \brief
* Constructor of foreach tuple pack helper
*
* \param args ... the actual begin/end source classes
*/
const_tuple_foreach ( const Types & ... args ) : data ( args ... ) { }
* Getter of pack of begin iterators.
*
* \return the iterator tuple class
*/
const_tuple_foreach_iterator < typename Types::const_iterator ... > begin ( ) const {
return callBegin ( std::index_sequence_for < Types ... > { } );
* Getter of pack of end iterators.
*
* \return the iterator tuple class
*/
const_tuple_foreach_iterator < typename Types::const_iterator ... > end ( ) const {
return callEnd ( std::index_sequence_for < Types ... > { } );
/**
* \brief
* Function construction of foreach tuple pack helper
*
* \tparam Types ... the types of begin/end source classes
*
* \param args ... the actual begin/end source classes
*
* \return the tuple of iterators itself mimicking the iterator interface to some level
*/
template < class ... Types >
const_tuple_foreach < Types ... > make_tuple_foreach ( const Types & ... args ) {
return const_tuple_foreach < Types ... > ( args ... );
/**
* \brief
* Class wrapping an integral type, but with pointer iterface.
*
* \tparam IntegralType the type of values the iterator provides
template < class IntegralType >
class virtual_pointer_to_integer {
* The value of integral type.
*/
typedef IntegralType value_type;
typedef std::ptrdiff_t difference_type;
typedef IntegralType * pointer;
typedef IntegralType reference;
typedef std::bidirectional_iterator_tag iterator_category;
* Constructor of the virtual pointer class.
*
* \param data the value to hold
*/
virtual_pointer_to_integer ( IntegralType data ) : m_data ( data ) {
}
* Method to retrieve the integral value.
*
* \return the current value
*/
IntegralType operator * ( ) const {
return m_data;
}
/**
* \brief
* Prefix increment operator to increment the hold value.
*
* \return this
*/
virtual_pointer_to_integer & operator ++( ) {
m_data ++;
return * this;
}
/**
* \brief
* Prefix decrement operator to decrement the hold value.
*
* \return this
*/
virtual_pointer_to_integer & operator --( ) {
m_data --;
return * this;
}
/**
* \brief
* Postfix increment operator to increment the hold value.
*
* \return original value
*/
virtual_pointer_to_integer operator ++( int ) {
virtual_pointer_to_integer temp = * this;
++( * this );
return temp;
}
/**
* \brief
* Postfix decrement operator to decrement the hold value.
*
* \return original value
*/
virtual_pointer_to_integer operator --( int ) {
virtual_pointer_to_integer temp = * this;
--( * this );
return temp;
}
/**
* \brief
* Equality operator. Two classes are equal if the data they hold is the same.
*
* \param other the other instance to compare with
*
* \return bool true if this and other classes hold the same value
*/
bool operator ==( const virtual_pointer_to_integer < IntegralType > & other ) {
return this->m_data == other.m_data;
}
/**
* \brief
* Inequality operator. Two classes are not equal if the data they hold is different.
*
* \param other the other instance to compare with
*
* \return bool true if this and other classes hold different value
*/
bool operator !=( const virtual_pointer_to_integer < IntegralType > & other ) {
return !( * this == other );
}
};
/**
* \brief
* Representation of integer sequence usable in foreach form of for loop.
*
* The class provides begin and end iterators.
*/
template < class IntegralType >
class sequence {
* The start value of the sequence. Included in the sequence.
*/
* The end value of the sequence. Not included in the sequence.
*/
* The constructor of the sequence based on the range
*
* \param first the start value of the sequence
* \param last the end value of the sequence
*/
sequence ( IntegralType first, IntegralType last ) : m_first ( first ), m_last ( last ) {
}
* \brief
* Constructor of the sequence class based on the size.
*
* \param size the length of the sequence from zero
*/
sequence ( IntegralType size ) : m_first ( 0 ), m_last ( size ) {
}
* Getter of the begin iterator into the sequence.
*
* \return iterator to the begining of the sequence
*/
virtual_pointer_to_integer < IntegralType > begin ( ) {
return virtual_pointer_to_integer < IntegralType > ( m_first );
}
* Getter of the end iterator into the sequence.
*
* \return iterator to the end of the sequence
*/
virtual_pointer_to_integer < IntegralType > end ( ) {
return virtual_pointer_to_integer < IntegralType > ( m_last );
}
};