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 diff --git a/include/boost/iterator/advance.hpp b/include/boost/iterator/advance.hpp new file mode 100644 index 0000000..6f81cdb --- /dev/null +++ b/include/boost/iterator/advance.hpp @@ -0,0 +1,84 @@ +// 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 + +namespace boost { +namespace iterators { + + namespace detail { + template + inline BOOST_CXX14_CONSTEXPR void + advance_impl( + InputIterator& it + , Distance n + , incrementable_traversal_tag + ) + { + while (n > 0) { + ++it; + --n; + } + } + + template + inline BOOST_CXX14_CONSTEXPR void + advance_impl( + BidirectionalIterator& it + , Distance 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 + , Distance n + , random_access_traversal_tag + ) + { + it += n; + } + } + + namespace advance_adl_barrier { + template + inline BOOST_CXX14_CONSTEXPR void + advance(InputIterator& it, Distance 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 diff --git a/include/boost/iterator/reverse_iterator.hpp b/include/boost/iterator/reverse_iterator.hpp index 3bef39e..7ed6b1b 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 #include @@ -40,14 +39,19 @@ 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(); } void advance(typename super_t::difference_type n) { - this->base_reference() += -n; + this->base_reference() -= n; } template 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 ] ; diff --git a/test/advance_test.cpp b/test/advance_test.cpp new file mode 100644 index 0000000..85cd4ac --- /dev/null +++ b/test/advance_test.cpp @@ -0,0 +1,91 @@ +// 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); + + 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::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 new file mode 100644 index 0000000..91587d6 --- /dev/null +++ b/test/distance_test.cpp @@ -0,0 +1,84 @@ +// 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); + + 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::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(); +}