From 663a30f659aefb1d8464d08b8a2a4eddb32dc8b4 Mon Sep 17 00:00:00 2001 From: morinmorin Date: Thu, 29 Jun 2017 22:06:12 +0900 Subject: [PATCH] Implement BoostIteratorTraversalConcepts-aware boost::advance/distance --- include/boost/iterator/advance.hpp | 85 +++++++++++++++++++++++++++++ include/boost/iterator/distance.hpp | 65 ++++++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 include/boost/iterator/advance.hpp create mode 100644 include/boost/iterator/distance.hpp diff --git a/include/boost/iterator/advance.hpp b/include/boost/iterator/advance.hpp new file mode 100644 index 0000000..2698f2b --- /dev/null +++ b/include/boost/iterator/advance.hpp @@ -0,0 +1,85 @@ +// Copyright (C) 2017 Michel Morin. +// +// 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) + +#ifndef BOOST_ITERATOR_ADVANCE_HPP +#define BOOST_ITERATOR_ADVANCE_HPP + +#include +#include +#include + +namespace boost { +namespace iterators { + + namespace detail { + template + inline BOOST_CXX14_CONSTEXPR void + advance_impl( + InputIterator& it + , typename iterator_difference::type n + , incrementable_traversal_tag + ) + { + while (n > 0) { + ++it; + --n; + } + } + + template + inline BOOST_CXX14_CONSTEXPR void + advance_impl( + BidirectionalIterator& it + , typename iterator_difference::type n + , bidirectional_traversal_tag + ) + { + if (n >= 0) { + while (n > 0) { + ++it; + --n; + } + } + else { + while (n < 0) { + --it; + ++n; + } + } + } + + template + inline BOOST_CXX14_CONSTEXPR void + advance_impl( + RandomAccessIterator& it + , typename iterator_difference::type n + , random_access_traversal_tag + ) + { + it += n; + } + } + + namespace advance_adl_barrier { + template + inline BOOST_CXX14_CONSTEXPR void + advance(InputIterator& it, typename iterator_difference::type n) + { + detail::advance_impl( + it, n, typename iterator_traversal::type() + ); + } + } + + using namespace advance_adl_barrier; + +} // namespace iterators + +using iterators::advance; + +} // namespace boost + +#endif diff --git a/include/boost/iterator/distance.hpp b/include/boost/iterator/distance.hpp new file mode 100644 index 0000000..8cf3f15 --- /dev/null +++ b/include/boost/iterator/distance.hpp @@ -0,0 +1,65 @@ +// Copyright (C) 2017 Michel Morin. +// +// 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) + +#ifndef BOOST_ITERATOR_DISTANCE_HPP +#define BOOST_ITERATOR_DISTANCE_HPP + +#include +#include +#include + +namespace boost { +namespace iterators { + + namespace detail { + template + inline BOOST_CXX14_CONSTEXPR typename iterator_difference::type + distance_impl( + SinglePassIterator first + , SinglePassIterator last + , single_pass_traversal_tag + ) + { + typename iterator_difference::type n = 0; + while (first != last) { + ++first; + ++n; + } + return n; + } + + template + inline BOOST_CXX14_CONSTEXPR typename iterator_difference::type + distance_impl( + RandomAccessIterator first + , RandomAccessIterator last + , random_access_traversal_tag + ) + { + return last - first; + } + } + + namespace distance_adl_barrier { + template + inline BOOST_CXX14_CONSTEXPR typename iterator_difference::type + distance(SinglePassIterator first, SinglePassIterator last) + { + return detail::distance_impl( + first, last, typename iterator_traversal::type() + ); + } + } + + using namespace distance_adl_barrier; + +} // namespace iterators + +using iterators::distance; + +} // namespace boost + +#endif