#ifndef PSTADE_OVEN_INDIRECT_RANGE_HPP
#define PSTADE_OVEN_INDIRECT_RANGE_HPP
///////////////////////////////////////////////////////////////////////////////
// PStade.Oven
//
// Copyright 2006 MB.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Boost.RangeEx
//
// Copyright 2004 Eric Niebler.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/foreach.hpp> // foreach::tag
#include <boost/iterator/indirect_iterator.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/result_iterator.hpp>
#include <pstade/egg/function.hpp>
#include "./range_adaptor.hpp"
namespace pstade { namespace oven {
///////////////////////////////////////////////////////////////////////////////
// indirect_range
//
template<
class Range,
class Value = boost::use_default,
class CategoryOrTraversal = boost::use_default,
class Reference = boost::use_default,
class Difference = boost::use_default
>
struct indirect_range :
boost::iterator_range<
boost::indirect_iterator<
typename boost::range_result_iterator<Range>::type,
Value,
CategoryOrTraversal,
Reference,
Difference
>
>
{
typedef typename boost::range_result_iterator<Range>::type base_iterator;
private:
typedef boost::indirect_iterator<
base_iterator,
Value,
CategoryOrTraversal,
Reference,
Difference
> iter_t;
typedef boost::iterator_range<iter_t> super_t;
public:
explicit indirect_range(Range& rng) :
super_t(
iter_t(boost::begin(rng)), iter_t(boost::end(rng))
)
{ }
};
namespace indirect_range_detail {
struct baby_generator
{
template< class Range >
struct apply
{
typedef indirect_range<Range> type;
};
template< class Result, class Range >
Result call(Range& rng)
{
return Result(rng);
}
};
} // namespace indirect_range_detail
///////////////////////////////////////////////////////////////////////////////
// make_indirect_range
//
PSTADE_EGG_FUNCTION(make_indirect_range, indirect_range_detail::baby_generator)
///////////////////////////////////////////////////////////////////////////////
// indirected
//
PSTADE_OVEN_RANGE_ADAPTOR(indirected, indirect_range_detail::baby_generator)
} } // namespace pstade::oven
///////////////////////////////////////////////////////////////////////////////
// Boost.Foreach optimization
//
template< class Range, class Value, class CategoryOrTraversal, class Reference, class Difference > inline
boost::mpl::true_
*boost_foreach_is_lightweight_proxy(pstade::oven::indirect_range<Range, Value, CategoryOrTraversal, Reference, Difference> *&, boost::foreach::tag)
{ return 0; }
///////////////////////////////////////////////////////////////////////////////
#endif