3
0
mirror of https://github.com/triqs/dft_tools synced 2024-11-01 03:33:50 +01:00
dft_tools/triqs/utility/dressed_iterator.hpp

114 lines
5.4 KiB
C++
Raw Normal View History

/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2013 by O. Parcollet
*
* TRIQS 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.
*
* TRIQS 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
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#ifndef TRIQS_UTILITY_ITERATOR_DRESSING_H
#define TRIQS_UTILITY_ITERATOR_DRESSING_H
#include "./first_include.hpp"
#include<iterator>
#include <boost/iterator/iterator_facade.hpp>
#include "./macros.hpp"
namespace triqs { namespace utility {
/**
* Usage :
*
* Suppose we have :
* - an iterator of type IteratorType
* - a little struct that views the data pointed to by it using a set of references,
* like e.g. :
*
* struct _dress {double const & tau; int & a; _dress ( it_type const & it); };
*
* then dressed_iterator<IteratorType, _dress> is :
*
* - a bidirectional or forward iterator (depending whether IteratorType is), STL compliant (generated by boost::iterator_facade).
* - that is dereferenced to a _dress.
*
* Example : See doc or test/utility/iterator_dressing.cpp ...
*
*
* Variant : one can keep in the iterator a pointer to anything (typically the parent container)
* which may be useful in some cases (e.g. writing cyclic iterators)
* See iterator_dressing3 for an example
*/
template< typename IteratorType, typename Dressing, typename DressingAuxiliaryArgumentPtrType = void> struct dressed_iterator;
namespace details {
template< typename IteratorType> struct is_bidir: std::is_same<typename IteratorType::iterator_category,std::bidirectional_iterator_tag>{};
}
// specialization when a aux data is present
template< typename IteratorType, typename Dressing, typename DressingAuxiliaryArgumentPtrType>
struct dressed_iterator : public boost::iterator_facade<dressed_iterator<IteratorType,Dressing,DressingAuxiliaryArgumentPtrType>, Dressing,
typename std::conditional<details::is_bidir<IteratorType>::value, boost::bidirectional_traversal_tag, boost::forward_traversal_tag>::type, Dressing > {
public :
dressed_iterator () {}
template<typename T> dressed_iterator (T const & it, DressingAuxiliaryArgumentPtrType * aux): _it(it), _aux(aux) {}
dressed_iterator (dressed_iterator const & it) = default;
dressed_iterator (dressed_iterator && it) = default;
dressed_iterator & operator = (dressed_iterator const & it) =default;
dressed_iterator & operator = (dressed_iterator && it) noexcept { using std::swap; swap(it._it, this->_it); swap(this->_aux, it._aux); return *this;}
//dressed_iterator (IteratorType const & it, DressingAuxiliaryArgumentPtrType * aux): _it(it), _aux(aux) {}
IteratorType const & get() const { return _it;}
IteratorType & get() { return _it;}
operator IteratorType() const { return _it;}
DressingAuxiliaryArgumentPtrType * get_aux() { return _aux;}
const DressingAuxiliaryArgumentPtrType * get_aux() const { return _aux;}
private:
friend class boost::iterator_core_access;
void increment(){ ++_it;}
template<bool BiDir = details::is_bidir<IteratorType>::value>
ENABLE_IFC(BiDir) decrement(){ --_it;}
bool equal(dressed_iterator const & other) const { return(other._it==_it);}
Dressing dereference() const { return Dressing(_it,_aux); }
IteratorType _it;
DressingAuxiliaryArgumentPtrType * _aux;// keep a pointer to maintain assignment of iterator !
};
// specialisation when no auxiliary data is present
template< typename IteratorType, typename Dressing>
struct dressed_iterator<IteratorType, Dressing,void> : public boost::iterator_facade<dressed_iterator<IteratorType,Dressing>,
Dressing, typename std::conditional<details::is_bidir<IteratorType>::value, boost::bidirectional_traversal_tag, boost::forward_traversal_tag>::type, Dressing > {
public :
dressed_iterator () {}
template<typename T> dressed_iterator (T const & it): _it(it) {}
dressed_iterator (dressed_iterator const & it) = default;
dressed_iterator (dressed_iterator && it) = default;
dressed_iterator & operator = (dressed_iterator const & it) =default;
dressed_iterator & operator = (dressed_iterator && it) noexcept { using std::swap; swap(it._it, this->_it); return *this;}
//dressed_iterator (IteratorType const & it): _it(it) {}
IteratorType const & get() const { return _it;}
IteratorType & get() { return _it;}
operator IteratorType() const { return _it;}
private:
friend class boost::iterator_core_access;
void increment(){ ++_it;}
template<bool BiDir = details::is_bidir<IteratorType>::value>
ENABLE_IFC(BiDir) decrement(){ --_it;}
bool equal(dressed_iterator const & other) const { return(other._it==_it);}
Dressing dereference() const { return Dressing(_it); }
IteratorType _it;
};
}}
#endif