2016-11-19 17:24:52 +00:00
/*
2018-09-02 00:57:29 +00:00
* This file is part of the DXX - Rebirth project < https : //www.dxx-rebirth.com/>.
2016-11-19 17:24:52 +00:00
* It is copyright by its individual contributors , as recorded in the
* project ' s Git history . See COPYING . txt at the top level for license
* terms and a link to the Git history .
*/
# pragma once
# include <inttypes.h>
2019-06-27 03:26:20 +00:00
# include <iterator>
2016-11-19 17:24:52 +00:00
# include "dxxsconf.h"
# include "partial_range.h"
2019-05-04 18:27:36 +00:00
# include "ephemeral_range.h"
2016-11-19 17:24:52 +00:00
/*
* This could have been done using a std : : pair , but using a custom type
* allows for more descriptive member names .
*/
template < typename range_value_type , typename index_type >
struct enumerated_value
{
2019-05-04 18:27:36 +00:00
range_value_type value ;
2016-11-19 17:24:52 +00:00
const index_type idx ;
} ;
template < typename range_iterator_type , typename index_type , typename result_type >
2019-06-27 03:26:20 +00:00
class enumerated_iterator : public std : : iterator < std : : forward_iterator_tag , result_type >
2016-11-19 17:24:52 +00:00
{
range_iterator_type m_iter ;
index_type m_idx ;
public :
enumerated_iterator ( const range_iterator_type & iter , const index_type idx ) :
m_iter ( iter ) , m_idx ( idx )
{
}
result_type operator * ( ) const
{
2019-05-04 18:27:36 +00:00
return result_type { * m_iter , m_idx } ;
2016-11-19 17:24:52 +00:00
}
enumerated_iterator & operator + + ( )
{
+ + m_iter ;
+ + m_idx ;
return * this ;
}
bool operator ! = ( const enumerated_iterator & i ) const
{
return m_iter ! = i . m_iter ;
}
2019-08-24 18:14:16 +00:00
bool operator = = ( const enumerated_iterator & i ) const
{
return m_iter = = i . m_iter ;
}
2016-11-19 17:24:52 +00:00
} ;
template < typename range_iterator_type , typename index_type >
class enumerated_range : partial_range_t < range_iterator_type >
{
using base_type = partial_range_t < range_iterator_type > ;
2019-05-04 18:27:36 +00:00
using iterator_dereference_type = decltype ( * std : : declval < range_iterator_type > ( ) ) ;
using enumerated_iterator_type = enumerated_iterator < range_iterator_type , index_type , enumerated_value < iterator_dereference_type , index_type > > ;
2016-11-19 17:24:52 +00:00
const index_type m_idx ;
public :
2019-05-04 18:27:36 +00:00
using range_owns_iterated_storage = std : : false_type ;
2016-11-19 17:24:52 +00:00
enumerated_range ( const range_iterator_type b , const range_iterator_type e , const index_type i ) :
base_type ( b , e ) , m_idx ( i )
{
}
template < typename range_type >
2019-05-04 18:27:36 +00:00
enumerated_range ( range_type & & t , const index_type i ) :
2016-11-19 17:24:52 +00:00
base_type ( t ) , m_idx ( i )
{
2019-05-04 18:27:36 +00:00
static_assert ( std : : is_rvalue_reference < range_type & & > : : value | | std : : is_lvalue_reference < iterator_dereference_type > : : value , " lvalue range must produce lvalue reference enumerated_value " ) ;
2016-11-19 17:24:52 +00:00
}
enumerated_iterator_type begin ( ) const
{
return enumerated_iterator_type ( this - > base_type : : begin ( ) , m_idx ) ;
}
enumerated_iterator_type end ( ) const
{
return enumerated_iterator_type ( this - > base_type : : end ( ) , 0 /* unused */ ) ;
}
} ;
template < typename range_type , typename index_type = uint_fast32_t , typename range_iterator_type = decltype ( begin ( std : : declval < range_type & > ( ) ) ) >
2019-05-04 18:27:36 +00:00
static auto enumerate ( range_type & & r , const index_type start = 0 )
2016-11-19 17:24:52 +00:00
{
2019-05-04 18:27:36 +00:00
static_assert ( ! any_ephemeral_range < range_type & & > : : value , " cannot enumerate storage of ephemeral ranges " ) ;
return enumerated_range < range_iterator_type , index_type > ( std : : forward < range_type > ( r ) , start ) ;
2016-11-19 17:24:52 +00:00
}