diff --git a/include/boost/iterator/advance.hpp b/include/boost/iterator/advance.hpp index 20a59a05d..e23a2444d 100644 --- a/include/boost/iterator/advance.hpp +++ b/include/boost/iterator/advance.hpp @@ -8,8 +8,11 @@ #define BOOST_ITERATOR_ADVANCE_HPP #include +#include #include +#include + namespace boost { namespace iterators { namespace detail { @@ -56,7 +59,9 @@ inline BOOST_CXX14_CONSTEXPR void advance_impl(RandomAccessIterator& it, Distanc namespace advance_adl_barrier { template< typename InputIterator, typename Distance > -inline BOOST_CXX14_CONSTEXPR void advance(InputIterator& it, Distance n) +inline BOOST_CXX14_CONSTEXPR +typename std::enable_if< boost::is_iterator< InputIterator >::value, void >::type +advance(InputIterator& it, Distance n) { detail::advance_impl(it, n, typename iterator_traversal< InputIterator >::type()); } diff --git a/include/boost/iterator/distance.hpp b/include/boost/iterator/distance.hpp index b1e32451f..6e4dac116 100644 --- a/include/boost/iterator/distance.hpp +++ b/include/boost/iterator/distance.hpp @@ -1,4 +1,5 @@ // Copyright (C) 2017 Michel Morin. +// Copyright (C) 2026 Jeremy W. Murphy // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -8,9 +9,12 @@ #define BOOST_ITERATOR_DISTANCE_HPP #include +#include #include #include +#include + namespace boost { namespace iterators { namespace detail { @@ -40,7 +44,11 @@ distance_impl(RandomAccessIterator first, RandomAccessIterator last, random_acce namespace distance_adl_barrier { template< typename SinglePassIterator > -inline BOOST_CXX14_CONSTEXPR typename iterator_difference< SinglePassIterator >::type +inline BOOST_CXX14_CONSTEXPR +typename std::enable_if< + boost::is_iterator< SinglePassIterator >::value, + iterator_difference< SinglePassIterator > +>::type::type distance(SinglePassIterator first, SinglePassIterator last) { return detail::distance_impl(first, last, typename iterator_traversal< SinglePassIterator >::type()); diff --git a/test/advance_test.cpp b/test/advance_test.cpp index 85cd4ac68..607f13120 100644 --- a/test/advance_test.cpp +++ b/test/advance_test.cpp @@ -20,6 +20,18 @@ void test_advance(Iterator it_from, Iterator it_to, int n) BOOST_TEST(it_from == it_to); } +// Definitely not an iterator +struct Foo +{ + int x = 0; + + friend + void advance(Foo &value, int n) + { + value.x += 10 * n; + } +}; + int main() { int array[3] = {1, 2, 3}; @@ -87,5 +99,12 @@ int main() ); } + { + using boost::advance; + Foo bar; + advance(bar, 3); + BOOST_TEST(bar.x == 30); + } + return boost::report_errors(); } diff --git a/test/distance_test.cpp b/test/distance_test.cpp index 91587d670..ab79e2391 100644 --- a/test/distance_test.cpp +++ b/test/distance_test.cpp @@ -4,6 +4,7 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#include #include #include #include @@ -19,6 +20,13 @@ void test_distance(Iterator it_from, Iterator it_to, int n) BOOST_TEST(boost::distance(it_from, it_to) == n); } +// Definitely not an iterator. +struct Foo +{ + constexpr friend + std::ptrdiff_t distance(Foo const &, Foo const &) { return -1; } +}; + int main() { int array[3] = {1, 2, 3}; @@ -80,5 +88,11 @@ int main() ); } + { + // Make boost::distance visible since we're not actually in the boost namespace here. + using boost::distance; + auto result = distance(Foo{}, Foo{}); + BOOST_TEST(result == -1); + } return boost::report_errors(); }