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.
This commit is contained in:
Andrey Semashev 2022-11-09 19:17:26 +03:00
parent f82627f2cc
commit 853ba3d3c7

View File

@ -28,6 +28,9 @@ namespace boost {
namespace iterators { namespace iterators {
template <class Function, class Input>
class function_input_iterator;
namespace impl { namespace impl {
// Computes the return type of an lvalue-call with an empty argument, // Computes the return type of an lvalue-call with an empty argument,
@ -46,21 +49,21 @@ namespace iterators {
}; };
template <class Function, class Input> template <class Function, class Input>
class function_input_iterator : class function_object_input_iterator :
public iterator_facade< public iterator_facade<
function_input_iterator<Function, Input>, iterators::function_input_iterator<Function, Input>,
typename result_of_nullary_lvalue_call<Function>::type, typename result_of_nullary_lvalue_call<Function>::type,
single_pass_traversal_tag, single_pass_traversal_tag,
typename result_of_nullary_lvalue_call<Function>::type const & typename result_of_nullary_lvalue_call<Function>::type const &
> >
{ {
public: public:
function_input_iterator() {} function_object_input_iterator() {}
function_input_iterator(Function & f_, Input state_ = Input()) function_object_input_iterator(Function & f_, Input state_ = Input())
: f(boost::addressof(f_)), state(state_) {} : f(boost::addressof(f_)), state(state_) {}
void increment() { void increment() {
if(value) if (value)
value = none; value = none;
else else
(*f)(); (*f)();
@ -69,10 +72,12 @@ namespace iterators {
typename result_of_nullary_lvalue_call<Function>::type const & typename result_of_nullary_lvalue_call<Function>::type const &
dereference() 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; return f == other.f && state == other.state;
} }
@ -85,7 +90,7 @@ namespace iterators {
template <class Function, class Input> template <class Function, class Input>
class function_pointer_input_iterator : class function_pointer_input_iterator :
public iterator_facade< public iterator_facade<
function_pointer_input_iterator<Function, Input>, iterators::function_input_iterator<Function, Input>,
typename function_types::result_type<Function>::type, typename function_types::result_type<Function>::type,
single_pass_traversal_tag, single_pass_traversal_tag,
typename function_types::result_type<Function>::type const & typename function_types::result_type<Function>::type const &
@ -97,7 +102,7 @@ namespace iterators {
: f(f_), state(state_) {} : f(f_), state(state_) {}
void increment() { void increment() {
if(value) if (value)
value = none; value = none;
else else
(*f)(); (*f)();
@ -106,7 +111,9 @@ namespace iterators {
typename function_types::result_type<Function>::type const & typename function_types::result_type<Function>::type const &
dereference() 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 { bool equal(function_pointer_input_iterator const & other) const {
@ -126,13 +133,13 @@ namespace iterators {
public boost::conditional< public boost::conditional<
function_types::is_function_pointer<Function>::value, function_types::is_function_pointer<Function>::value,
impl::function_pointer_input_iterator<Function,Input>, impl::function_pointer_input_iterator<Function,Input>,
impl::function_input_iterator<Function,Input> impl::function_object_input_iterator<Function,Input>
>::type >::type
{ {
typedef typename boost::conditional< typedef typename boost::conditional<
function_types::is_function_pointer<Function>::value, function_types::is_function_pointer<Function>::value,
impl::function_pointer_input_iterator<Function,Input>, impl::function_pointer_input_iterator<Function,Input>,
impl::function_input_iterator<Function,Input> impl::function_object_input_iterator<Function,Input>
>::type base_type; >::type base_type;
public: public:
function_input_iterator(Function & f, Input i) function_input_iterator(Function & f, Input i)