From e968c3312b8edffa75f9d6c109aeddedb7b6436d Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Mon, 9 Jun 2025 04:41:53 +0300 Subject: [PATCH] Forward dereferencing operators in operator_brackets_proxy. This allows for expressions like it[n]->foo() and (*it[n]).foo() to compile. --- include/boost/iterator/iterator_facade.hpp | 15 ++++++++++++++- test/iterator_adaptor_test.cpp | 10 ++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/include/boost/iterator/iterator_facade.hpp b/include/boost/iterator/iterator_facade.hpp index 0604b3c..0c6b356 100644 --- a/include/boost/iterator/iterator_facade.hpp +++ b/include/boost/iterator/iterator_facade.hpp @@ -365,12 +365,25 @@ public: typename std::remove_cv< typename std::remove_reference< T >::type >::type >::value, operator_brackets_proxy& - >::type operator= (T&& val) noexcept(std::is_nothrow_assignable< reference, T&& >::value) + >::type operator= (T&& val) noexcept(noexcept(*std::declval< Iterator const& >() = std::declval< T&& >())) { *m_iter = static_cast< T&& >(val); return *this; } + // Provides it[n]->foo(). Leverages chaining of operator->. + reference operator->() const noexcept(noexcept(*std::declval< Iterator const& >())) + { + return *m_iter; + } + + // Provides (*it[n]).foo() + template< typename Ref = reference, typename Result = decltype(*std::declval< Ref >()) > + Result operator*() const noexcept(noexcept(**std::declval< Iterator const& >())) + { + return **m_iter; + } + private: Iterator m_iter; }; diff --git a/test/iterator_adaptor_test.cpp b/test/iterator_adaptor_test.cpp index d237ac4..dc67e2a 100644 --- a/test/iterator_adaptor_test.cpp +++ b/test/iterator_adaptor_test.cpp @@ -189,6 +189,16 @@ main() boost::const_nonconst_iterator_test(i, ++j); } + // Test that operator_brackets_proxy forwards operator-> and operator* + { + dummyT* ptr_array[] = { array + 0, array + 1, array + 2, + array + 3, array + 4, array + 5 }; + + ptr_iterator i(ptr_array); + BOOST_TEST_EQ(i[2]->foo(), 2); + BOOST_TEST_EQ((*i[2]).foo(), 2); + } + int test; // Test the iterator_traits {