From 663a30f659aefb1d8464d08b8a2a4eddb32dc8b4 Mon Sep 17 00:00:00 2001 From: morinmorin Date: Thu, 29 Jun 2017 22:06:12 +0900 Subject: [PATCH 1/8] 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 From d5b67c7fab505e7fffb6288d082eb4b317880aa6 Mon Sep 17 00:00:00 2001 From: morinmorin Date: Thu, 29 Jun 2017 22:09:26 +0900 Subject: [PATCH 2/8] Add tests for boost::advance/distance --- test/advance_test.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++ test/distance_test.cpp | 63 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 test/advance_test.cpp create mode 100644 test/distance_test.cpp diff --git a/test/advance_test.cpp b/test/advance_test.cpp new file mode 100644 index 0000000..230d07e --- /dev/null +++ b/test/advance_test.cpp @@ -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) + +#include +#include +#include +#include +#include +#include + +int twice(int x) { return x + x; } + +template +void test_advance(Iterator it_from, Iterator it_to, int n) +{ + boost::advance(it_from, n); + BOOST_TEST(it_from == it_to); +} + +int main() +{ + int array[3] = {1, 2, 3}; + int* ptr1 = array; + int* ptr2 = array + 3; + + { + test_advance(ptr1, ptr2, 3); + test_advance(ptr2, ptr1, -3); + } + + { + std::vector ints(ptr1, ptr2); + test_advance(ints.begin(), ints.end(), 3); + test_advance(ints.end(), ints.begin(), -3); + } + + { + test_advance( + boost::make_transform_iterator(ptr1, twice) + , boost::make_transform_iterator(ptr2, twice) + , 3 + ); + test_advance( + boost::make_transform_iterator(ptr2, twice) + , boost::make_transform_iterator(ptr1, twice) + , -3 + ); + } + + { + std::list ints(ptr1, ptr2); + test_advance(ints.begin(), ints.end(), 3); + test_advance(ints.end(), ints.begin(), -3); + } + + { + boost::container::slist ints(ptr1, ptr2); + test_advance(ints.begin(), ints.end(), 3); + } + + return boost::report_errors(); +} diff --git a/test/distance_test.cpp b/test/distance_test.cpp new file mode 100644 index 0000000..494b0d5 --- /dev/null +++ b/test/distance_test.cpp @@ -0,0 +1,63 @@ +// 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) + +#include +#include +#include +#include +#include +#include + +int twice(int x) { return x + x; } + +template +void test_distance(Iterator it_from, Iterator it_to, int n) +{ + BOOST_TEST(boost::distance(it_from, it_to) == n); +} + +int main() +{ + int array[3] = {1, 2, 3}; + int* ptr1 = array; + int* ptr2 = array + 3; + + { + test_distance(ptr1, ptr2, 3); + test_distance(ptr2, ptr1, -3); + } + + { + std::vector ints(ptr1, ptr2); + test_distance(ints.begin(), ints.end(), 3); + test_distance(ints.end(), ints.begin(), -3); + } + + { + test_distance( + boost::make_transform_iterator(ptr1, twice) + , boost::make_transform_iterator(ptr2, twice) + , 3 + ); + test_distance( + boost::make_transform_iterator(ptr2, twice) + , boost::make_transform_iterator(ptr1, twice) + , -3 + ); + } + + { + std::list ints(ptr1, ptr2); + test_distance(ints.begin(), ints.end(), 3); + } + + { + boost::container::slist ints(ptr1, ptr2); + test_distance(ints.begin(), ints.end(), 3); + } + + return boost::report_errors(); +} From bb54ee790004517009fe049f71da06af1b149fc9 Mon Sep 17 00:00:00 2001 From: morinmorin Date: Thu, 29 Jun 2017 22:49:05 +0900 Subject: [PATCH 3/8] Update Jamfile.v2 for new tests --- test/Jamfile.v2 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 81547dc..927a98a 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -55,4 +55,7 @@ test-suite iterator [ run minimum_category.cpp ] [ compile-fail minimum_category_compile_fail.cpp ] + + [ run advance_test.cpp ] + [ run distance_test.cpp ] ; From 847b2a1be3f2d6f0710016082a869cd763484084 Mon Sep 17 00:00:00 2001 From: Edward Diener Date: Fri, 30 Jun 2017 20:29:49 -0400 Subject: [PATCH 4/8] Added Travis testing --- .travis.yml | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..dc3a331 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,40 @@ +# Copyright 2016 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) + +language: cpp + +sudo: false + +python: "2.7" + +os: + - linux + - osx + +branches: + only: + - master + - develop + +install: + - cd .. + - git clone -b $TRAVIS_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + - cd boost-root + - git submodule update --init --depth 1 tools/build + - git submodule update --init --depth 1 libs/config + - git submodule update --init --depth 1 tools/boostdep + - cp -r $TRAVIS_BUILD_DIR/* libs/iterator + - python tools/boostdep/depinst/depinst.py iterator + - ./bootstrap.sh + - ./b2 headers + +script: + - TOOLSET=gcc,clang + - if [ $TRAVIS_OS_NAME == osx ]; then TOOLSET=clang; fi + - ./b2 --verbose-test libs/config/test//config_info toolset=$TOOLSET || true + - ./b2 libs/iterator/test toolset=$TOOLSET + +notifications: + email: + on_success: always From 029277f3edbf5084ea3a7eaeb072addbe1019d41 Mon Sep 17 00:00:00 2001 From: morinmorin Date: Sat, 8 Jul 2017 13:30:28 +0900 Subject: [PATCH 5/8] Add more tests for ReabableIterator --- test/advance_test.cpp | 42 ++++++++++++++++++++++++++++++++++-------- test/distance_test.cpp | 37 +++++++++++++++++++++++++++++-------- 2 files changed, 63 insertions(+), 16 deletions(-) diff --git a/test/advance_test.cpp b/test/advance_test.cpp index 230d07e..85cd4ac 100644 --- a/test/advance_test.cpp +++ b/test/advance_test.cpp @@ -29,15 +29,7 @@ int main() { test_advance(ptr1, ptr2, 3); test_advance(ptr2, ptr1, -3); - } - { - std::vector ints(ptr1, ptr2); - test_advance(ints.begin(), ints.end(), 3); - test_advance(ints.end(), ints.begin(), -3); - } - - { test_advance( boost::make_transform_iterator(ptr1, twice) , boost::make_transform_iterator(ptr2, twice) @@ -50,15 +42,49 @@ int main() ); } + { + std::vector ints(ptr1, ptr2); + test_advance(ints.begin(), ints.end(), 3); + test_advance(ints.end(), ints.begin(), -3); + + test_advance( + boost::make_transform_iterator(ints.begin(), twice) + , boost::make_transform_iterator(ints.end(), twice) + , 3 + ); + test_advance( + boost::make_transform_iterator(ints.end(), twice) + , boost::make_transform_iterator(ints.begin(), twice) + , -3 + ); + } + { std::list ints(ptr1, ptr2); test_advance(ints.begin(), ints.end(), 3); test_advance(ints.end(), ints.begin(), -3); + + test_advance( + boost::make_transform_iterator(ints.begin(), twice) + , boost::make_transform_iterator(ints.end(), twice) + , 3 + ); + test_advance( + boost::make_transform_iterator(ints.end(), twice) + , boost::make_transform_iterator(ints.begin(), twice) + , -3 + ); } { boost::container::slist ints(ptr1, ptr2); test_advance(ints.begin(), ints.end(), 3); + + test_advance( + boost::make_transform_iterator(ints.begin(), twice) + , boost::make_transform_iterator(ints.end(), twice) + , 3 + ); } return boost::report_errors(); diff --git a/test/distance_test.cpp b/test/distance_test.cpp index 494b0d5..91587d6 100644 --- a/test/distance_test.cpp +++ b/test/distance_test.cpp @@ -28,15 +28,7 @@ int main() { test_distance(ptr1, ptr2, 3); test_distance(ptr2, ptr1, -3); - } - { - std::vector ints(ptr1, ptr2); - test_distance(ints.begin(), ints.end(), 3); - test_distance(ints.end(), ints.begin(), -3); - } - - { test_distance( boost::make_transform_iterator(ptr1, twice) , boost::make_transform_iterator(ptr2, twice) @@ -49,14 +41,43 @@ int main() ); } + { + std::vector ints(ptr1, ptr2); + test_distance(ints.begin(), ints.end(), 3); + test_distance(ints.end(), ints.begin(), -3); + + test_distance( + boost::make_transform_iterator(ints.begin(), twice) + , boost::make_transform_iterator(ints.end(), twice) + , 3 + ); + test_distance( + boost::make_transform_iterator(ints.end(), twice) + , boost::make_transform_iterator(ints.begin(), twice) + , -3 + ); + } + { std::list ints(ptr1, ptr2); test_distance(ints.begin(), ints.end(), 3); + + test_distance( + boost::make_transform_iterator(ints.begin(), twice) + , boost::make_transform_iterator(ints.end(), twice) + , 3 + ); } { boost::container::slist ints(ptr1, ptr2); test_distance(ints.begin(), ints.end(), 3); + + test_distance( + boost::make_transform_iterator(ints.begin(), twice) + , boost::make_transform_iterator(ints.end(), twice) + , 3 + ); } return boost::report_errors(); From 26ee5ba75445bc1c84b64fb5489a300fef445ebe Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 9 Jul 2017 18:31:06 +0300 Subject: [PATCH 6/8] Remove dependency on boost::prior. --- include/boost/iterator/reverse_iterator.hpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/boost/iterator/reverse_iterator.hpp b/include/boost/iterator/reverse_iterator.hpp index 7dcf645..8446f23 100644 --- a/include/boost/iterator/reverse_iterator.hpp +++ b/include/boost/iterator/reverse_iterator.hpp @@ -7,7 +7,6 @@ #ifndef BOOST_REVERSE_ITERATOR_23022003THW_HPP #define BOOST_REVERSE_ITERATOR_23022003THW_HPP -#include #include namespace boost { @@ -39,7 +38,12 @@ namespace iterators { {} private: - typename super_t::reference dereference() const { return *boost::prior(this->base()); } + typename super_t::reference dereference() const + { + Iterator it = this->base_reference(); + --it; + return *it; + } void increment() { --this->base_reference(); } void decrement() { ++this->base_reference(); } From 5bfbfb771646187059438a404318d213525ccfbf Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Mon, 10 Jul 2017 14:51:07 +0300 Subject: [PATCH 7/8] Use a separate template parameter for distance in advance(). This follows std::advance interface and also allows to use distance types other than iterator's difference_type (if the iterator supports that). --- include/boost/iterator/advance.hpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/include/boost/iterator/advance.hpp b/include/boost/iterator/advance.hpp index 2698f2b..6f81cdb 100644 --- a/include/boost/iterator/advance.hpp +++ b/include/boost/iterator/advance.hpp @@ -9,17 +9,16 @@ #include #include -#include namespace boost { namespace iterators { namespace detail { - template + template inline BOOST_CXX14_CONSTEXPR void advance_impl( InputIterator& it - , typename iterator_difference::type n + , Distance n , incrementable_traversal_tag ) { @@ -29,11 +28,11 @@ namespace iterators { } } - template + template inline BOOST_CXX14_CONSTEXPR void advance_impl( BidirectionalIterator& it - , typename iterator_difference::type n + , Distance n , bidirectional_traversal_tag ) { @@ -51,11 +50,11 @@ namespace iterators { } } - template + template inline BOOST_CXX14_CONSTEXPR void advance_impl( RandomAccessIterator& it - , typename iterator_difference::type n + , Distance n , random_access_traversal_tag ) { @@ -64,9 +63,9 @@ namespace iterators { } namespace advance_adl_barrier { - template + template inline BOOST_CXX14_CONSTEXPR void - advance(InputIterator& it, typename iterator_difference::type n) + advance(InputIterator& it, Distance n) { detail::advance_impl( it, n, typename iterator_traversal::type() From c148962bd9fda115956d13d4ed600c4880dcc1c8 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Mon, 10 Jul 2017 14:57:40 +0300 Subject: [PATCH 8/8] Avoid integer overflow on negating distance --- include/boost/iterator/reverse_iterator.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/iterator/reverse_iterator.hpp b/include/boost/iterator/reverse_iterator.hpp index 8446f23..03b7925 100644 --- a/include/boost/iterator/reverse_iterator.hpp +++ b/include/boost/iterator/reverse_iterator.hpp @@ -50,7 +50,7 @@ namespace iterators { void advance(typename super_t::difference_type n) { - this->base_reference() += -n; + this->base_reference() -= n; } template