From 853ba3d3c773d75bf2ac7c100c9ef44821f76d8b Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Wed, 9 Nov 2022 19:17:26 +0300 Subject: [PATCH] Use the proper derived type of the function_input_iterator in iterator_facade. This fixes incorrect final iterator type being used in iterator_facade, which results in an internal base class being returned from various facade methods. Reported in https://github.com/boostorg/iterator/issues/75. --- .../iterator/function_input_iterator.hpp | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/include/boost/iterator/function_input_iterator.hpp b/include/boost/iterator/function_input_iterator.hpp index 11f87de..610c133 100644 --- a/include/boost/iterator/function_input_iterator.hpp +++ b/include/boost/iterator/function_input_iterator.hpp @@ -28,6 +28,9 @@ namespace boost { namespace iterators { + template + class function_input_iterator; + namespace impl { // Computes the return type of an lvalue-call with an empty argument, @@ -46,21 +49,21 @@ namespace iterators { }; template - class function_input_iterator : + class function_object_input_iterator : public iterator_facade< - function_input_iterator, + iterators::function_input_iterator, typename result_of_nullary_lvalue_call::type, single_pass_traversal_tag, typename result_of_nullary_lvalue_call::type const & > { public: - function_input_iterator() {} - function_input_iterator(Function & f_, Input state_ = Input()) + function_object_input_iterator() {} + function_object_input_iterator(Function & f_, Input state_ = Input()) : f(boost::addressof(f_)), state(state_) {} void increment() { - if(value) + if (value) value = none; else (*f)(); @@ -69,10 +72,12 @@ namespace iterators { typename result_of_nullary_lvalue_call::type const & dereference() const { - return (value ? value : value = (*f)()).get(); + if (!value) + value = (*f)(); + return value.get(); } - bool equal(function_input_iterator const & other) const { + bool equal(function_object_input_iterator const & other) const { return f == other.f && state == other.state; } @@ -85,7 +90,7 @@ namespace iterators { template class function_pointer_input_iterator : public iterator_facade< - function_pointer_input_iterator, + iterators::function_input_iterator, typename function_types::result_type::type, single_pass_traversal_tag, typename function_types::result_type::type const & @@ -97,7 +102,7 @@ namespace iterators { : f(f_), state(state_) {} void increment() { - if(value) + if (value) value = none; else (*f)(); @@ -106,7 +111,9 @@ namespace iterators { typename function_types::result_type::type const & dereference() const { - return (value ? value : value = (*f)()).get(); + if (!value) + value = (*f)(); + return value.get(); } bool equal(function_pointer_input_iterator const & other) const { @@ -126,13 +133,13 @@ namespace iterators { public boost::conditional< function_types::is_function_pointer::value, impl::function_pointer_input_iterator, - impl::function_input_iterator + impl::function_object_input_iterator >::type { typedef typename boost::conditional< function_types::is_function_pointer::value, impl::function_pointer_input_iterator, - impl::function_input_iterator + impl::function_object_input_iterator >::type base_type; public: function_input_iterator(Function & f, Input i)