Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to return underlying container iterator (root) of adapted range #116

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 180 additions & 10 deletions include/boost/range/detail/range_return.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,34 @@
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/root_iterator_of.hpp>
#include <boost/next_prior.hpp>

namespace boost
{
enum range_return_value
{
// (*) indicates the most common values
return_found, // only the found resulting iterator (*)
return_next, // next(found) iterator
return_prior, // prior(found) iterator
return_begin_found, // [begin, found) range (*)
return_begin_next, // [begin, next(found)) range
return_begin_prior, // [begin, prior(found)) range
return_found_end, // [found, end) range (*)
return_next_end, // [next(found), end) range
return_prior_end, // [prior(found), end) range
return_begin_end // [begin, end) range
return_found, // only the found resulting iterator (*)
return_next, // next(found) iterator
return_prior, // prior(found) iterator
return_begin_found, // [begin, found) range (*)
return_begin_next, // [begin, next(found)) range
return_begin_prior, // [begin, prior(found)) range
return_found_end, // [found, end) range (*)
return_next_end, // [next(found), end) range
return_prior_end, // [prior(found), end) range
return_begin_end, // [begin, end) range
return_root_found, // only the found resulting root iterator (*)
return_root_next, // next(found) root iterator
return_root_prior, // prior(found) root iterator
return_root_begin_found, // [begin, found) root iterator range (*)
return_root_begin_next, // [begin, next(found)) root iterator range
return_root_begin_prior, // [begin, prior(found)) root iterator range
return_root_found_end, // [found, end) root iterator range (*)
return_root_next_end, // [next(found), end) root iterator range
return_root_prior_end, // [prior(found), end) root iterator range
return_root_begin_end, // [begin, end) root iterator range
};

template< class SinglePassRange, range_return_value >
Expand Down Expand Up @@ -176,6 +187,165 @@ namespace boost
}
};

template< class SinglePassRange >
struct range_return< SinglePassRange, return_root_found >
{
typedef BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type iterator;
typedef BOOST_DEDUCED_TYPENAME root_iterator_of<iterator>::type root_iterator;
// range return type
typedef root_iterator type;

static type pack(iterator found, SinglePassRange&)
{
return root_of(found);
}
};

template< class SinglePassRange >
struct range_return< SinglePassRange, return_root_next >
{
typedef BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type iterator;
typedef BOOST_DEDUCED_TYPENAME root_iterator_of<iterator>::type root_iterator;
// range return type
typedef root_iterator type;

static type pack(iterator found, SinglePassRange& rng)
{
return found == boost::end(rng)
? root_of(found)
: root_of(boost::next(found));
}
};

template< class BidirectionalRange >
struct range_return< BidirectionalRange, return_root_prior >
{
typedef BOOST_DEDUCED_TYPENAME range_iterator<BidirectionalRange>::type iterator;
typedef BOOST_DEDUCED_TYPENAME root_iterator_of<iterator>::type root_iterator;
// range return type
typedef root_iterator type;

static type pack(iterator found, BidirectionalRange& rng)
{
return found == boost::begin(rng)
? root_of(found)
: root_of(boost::prior(found));
}
};

template< class SinglePassRange >
struct range_return< SinglePassRange, return_root_begin_found >
{
typedef BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type iterator;
typedef BOOST_DEDUCED_TYPENAME root_iterator_of<iterator>::type root_iterator;
// range return type
typedef iterator_range<root_iterator> type;

static type pack(iterator found, SinglePassRange& rng)
{
return type( root_of(boost::begin(rng)),
root_of(found) );
}
};

template< class SinglePassRange >
struct range_return< SinglePassRange, return_root_begin_next >
{
typedef BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type iterator;
typedef BOOST_DEDUCED_TYPENAME root_iterator_of<iterator>::type root_iterator;
// range return type
typedef iterator_range<root_iterator> type;

static type pack(iterator found, SinglePassRange& rng)
{
return type( root_of(boost::begin(rng)),
found == boost::end(rng)
? root_of(found)
: root_of(boost::next(found)) );
}
};

template< class BidirectionalRange >
struct range_return< BidirectionalRange, return_root_begin_prior >
{
typedef BOOST_DEDUCED_TYPENAME range_iterator<BidirectionalRange>::type iterator;
typedef BOOST_DEDUCED_TYPENAME root_iterator_of<iterator>::type root_iterator;
// range return type
typedef iterator_range<root_iterator> type;

static type pack(iterator found, BidirectionalRange& rng)
{
return type( root_of(boost::begin(rng)),
found == boost::begin(rng)
? root_of(found)
: root_of(boost::prior(found)) );
}
};

template< class SinglePassRange >
struct range_return< SinglePassRange, return_root_found_end >
{
typedef BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type iterator;
typedef BOOST_DEDUCED_TYPENAME root_iterator_of<iterator>::type root_iterator;
// range return type
typedef iterator_range<root_iterator> type;

static type pack(iterator found, SinglePassRange& rng)
{
return type( root_of(found),
root_of(boost::end(rng)) );
}
};

template< class SinglePassRange >
struct range_return< SinglePassRange, return_root_next_end >
{
typedef BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type iterator;
typedef BOOST_DEDUCED_TYPENAME root_iterator_of<iterator>::type root_iterator;
// range return type
typedef iterator_range<root_iterator> type;

static type pack(iterator found, SinglePassRange& rng)
{
return type( found == boost::end(rng)
? root_of(found)
: root_of(boost::next(found)),
root_of(boost::end(rng)) );
}
};

template< class BidirectionalRange >
struct range_return< BidirectionalRange, return_root_prior_end >
{
typedef BOOST_DEDUCED_TYPENAME range_iterator<BidirectionalRange>::type iterator;
typedef BOOST_DEDUCED_TYPENAME root_iterator_of<iterator>::type root_iterator;
// range return type
typedef iterator_range<root_iterator> type;

static type pack(iterator found, BidirectionalRange& rng)
{
return type( found == boost::begin(rng)
? root_of(found)
: root_of(boost::prior(found)),
root_of(boost::end(rng)) );
}
};

template< class SinglePassRange >
struct range_return< SinglePassRange, return_root_begin_end >
{
typedef BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type iterator;
typedef BOOST_DEDUCED_TYPENAME root_iterator_of<iterator>::type root_iterator;
// range return type
typedef iterator_range<root_iterator> type;

static type pack(iterator, SinglePassRange& rng)
{
return type( root_of(boost::begin(rng)),
root_of(boost::end(rng)) );
}
};

}

#endif // include guard
91 changes: 91 additions & 0 deletions include/boost/range/root_iterator_of.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright Klaus Triendl 2020. Use, modification and
// distribution is subject to 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)
//
//
// For more information, see http://www.boost.org/libs/range/
//
#if defined(_MSC_VER)
#pragma once
#endif

#ifndef BOOST_RANGE_ROOT_ITERATOR_OF_HPP_INCLUDED
#define BOOST_RANGE_ROOT_ITERATOR_OF_HPP_INCLUDED

#include <boost/config.hpp> // BOOST_DEDUCED_TYPENAME
#include <boost/mpl/has_xxx.hpp>
#include <boost/range/iterator_range.hpp>


namespace boost
{

namespace range_detail
{

BOOST_MPL_HAS_XXX_TRAIT_DEF(base_type)

template<typename It, bool B = has_base_type<It>::value>
struct root_iterator_of_impl;

template<typename It>
struct root_iterator_of_impl<It, false>
{
typedef It type;
};

template<typename It>
struct root_iterator_of_impl<It, true> :
root_iterator_of_impl<BOOST_DEDUCED_TYPENAME It::base_type>
{};

template<typename It>
It root_of(It it, boost::mpl::bool_<false>)
{
return it;
}
template<typename It>
BOOST_DEDUCED_TYPENAME root_iterator_of_impl<It, true>::type
root_of(It it, boost::mpl::bool_<true>)
{
return root_of(it.base());
}

}

namespace range
{

template<typename It>
struct root_iterator_of :
range_detail::root_iterator_of_impl<It>
{};

#ifdef __cpp_alias_templates
template<typename It>
using root_iterator_of_t = typename root_iterator_of<It>::type;
#endif

template<typename It>
BOOST_DEDUCED_TYPENAME root_iterator_of<It>::type
root_of(It it)
{
return range_detail::root_of( it,
BOOST_DEDUCED_TYPENAME range_detail::has_base_type<It>::type{} );
}

template<typename It>
iterator_range<BOOST_DEDUCED_TYPENAME root_iterator_of<It>::type>
root_of(iterator_range<It> rng)
{
return make_iterator_range(root_of(rng.begin()), root_of(rng.end()));
}

}
using range::root_iterator_of;
using range::root_of;

}

#endif // include guard
Loading