Skip to content
Snippets Groups Projects
foreach.hpp 10.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • Jan Trávníček's avatar
    Jan Trávníček committed
    /*
     * foreach.hpp
     *
    
     * 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/>.
     *
    
    Jan Trávníček's avatar
    Jan Trávníček committed
     * Created on: Apr 1, 2013
     * Author: Jan Travnicek
     */
    
    #ifndef __FOREACH_HPP_
    #define __FOREACH_HPP_
    
    
    #include <tuple>
    #include <utility>
    
    
    #include "tuple.hpp"
    
    
    Jan Trávníček's avatar
    Jan Trávníček committed
    
    
    /**
     * \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.
    	 */
    
    	ext::tuple < Iterators ... > current;
    
    Jan Trávníček's avatar
    Jan Trávníček committed
    
    
    	/**
    	 * \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
    	 */
    
    	template < size_t ... I >
    
    	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
    	 */
    
    	template < size_t ... I >
    
    	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 );
    
    Jan Trávníček's avatar
    Jan Trávníček committed
    		return temp;
    	}
    
    
    	/**
    	 * \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 );
    
    Jan Trávníček's avatar
    Jan Trávníček committed
    		return temp;
    	}
    
    
    	/**
    	 * \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 ( ) ... );
    	}
    
    Jan Trávníček's avatar
    Jan Trávníček committed
    
    public:
    
    	/**
    	 * \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.
     *
     */
    
    template < class IntegralType >
    class virtual_pointer_to_integer {
    
    	/**
    	 * The value of integral type.
    	 */
    
    	IntegralType m_data;
    
    public:
    
    	/**
    	 * 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.
    	 */
    
    	IntegralType m_first;
    
    
    	/**
    	 * The end value of the sequence. Not included in the sequence.
    	 */
    
    	IntegralType m_last;
    
    public:
    
    	/**
    	 * 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 );
    	}
    };
    
    
    } /* namespace ext */
    
    Jan Trávníček's avatar
    Jan Trávníček committed
    
    #endif /* __FOREACH_HPP_ */