diff --git a/doc/function_input_iterator.rst b/doc/function_input_iterator.rst index d073fa0..55c35c8 100644 --- a/doc/function_input_iterator.rst +++ b/doc/function_input_iterator.rst @@ -1,10 +1,13 @@ :Author: - `Dean Michael Berris `_ + `Dean Michael Berris `_ :License: 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) +:Copyright: + Copyright 2012 Google, Inc. + Function Input Iterator ======================= @@ -58,7 +61,7 @@ Synopsis template typename function_input_iterator - make_function_input_iterator(Function & f); + make_function_input_iterator(Function & f, State s); struct infinite; } @@ -112,7 +115,7 @@ it with the ``boost::infinite`` helper class. copy( make_function_input_iterator(f,infinite()), make_function_input_iterator(f,infinite()), - ostream_iterator(count, " ") + ostream_iterator(cout, " ") ); Above, instead of creating a huge vector we rely on the STL copy algorithm diff --git a/include/boost/iterator/function_input_iterator.hpp b/include/boost/iterator/function_input_iterator.hpp index 8f1df68..82feffb 100644 --- a/include/boost/iterator/function_input_iterator.hpp +++ b/include/boost/iterator/function_input_iterator.hpp @@ -1,4 +1,6 @@ // Copyright 2009 (C) Dean Michael Berris +// Copyright 2012 (C) Google, Inc. +// Copyright 2012 (C) Jeffrey Lee Hellrung, Jr. // 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) @@ -7,11 +9,14 @@ #ifndef BOOST_FUNCTION_INPUT_ITERATOR #define BOOST_FUNCTION_INPUT_ITERATOR +#include #include #include #include #include #include +#include +#include namespace boost { @@ -29,16 +34,17 @@ namespace boost { public: function_input_iterator() {} function_input_iterator(Function & f_, Input state_ = Input()) - : f(&f_), state(state_), value((*f)()) {} + : f(&f_), state(state_) {} void increment() { - value = (*f)(); + BOOST_ASSERT(value); + value = none; ++state; } typename Function::result_type const & dereference() const { - return value; + return (value ? value : value = (*f)()).get(); } bool equal(function_input_iterator const & other) const { @@ -48,7 +54,7 @@ namespace boost { private: Function * f; Input state; - typename Function::result_type value; + mutable optional value; }; template @@ -63,17 +69,17 @@ namespace boost { public: function_pointer_input_iterator() {} function_pointer_input_iterator(Function &f_, Input state_ = Input()) - : f(f_), state(state_), value((*f)()) - {} + : f(f_), state(state_) {} void increment() { - value = (*f)(); + BOOST_ASSERT(value); + value = none; ++state; } typename function_types::result_type::type const & dereference() const { - return value; + return (value ? value : value = (*f)()).get(); } bool equal(function_pointer_input_iterator const & other) const { @@ -83,7 +89,7 @@ namespace boost { private: Function f; Input state; - typename function_types::result_type::type value; + mutable optional::type> value; }; template diff --git a/test/function_input_iterator_test.cpp b/test/function_input_iterator_test.cpp index 0fea9c1..b08caa6 100644 --- a/test/function_input_iterator_test.cpp +++ b/test/function_input_iterator_test.cpp @@ -3,12 +3,17 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include -#include -#include #include +#include + #include #include +#include +#include + +#include + +namespace { struct ones { typedef int result_type; @@ -21,6 +26,17 @@ int ones_function () { return 1; } +struct counter { + typedef int result_type; + int n; + explicit counter(int n_) : n(n_) { } + result_type operator() () { + return n++; + } +}; + +} // namespace + using namespace std; int main(int argc, char * argv[]) @@ -65,6 +81,21 @@ int main(int argc, char * argv[]) assert(equal(values.begin(), values.end(), generated.begin())); cout << "function iterator test with reference to function successful." << endl; + // test the iterator with a stateful function object + counter counter_generator(42); + vector().swap(generated); + copy( + boost::make_function_input_iterator(counter_generator, 0), + boost::make_function_input_iterator(counter_generator, 10), + back_inserter(generated) + ); + + assert(generated.size() == 10); + assert(counter_generator.n == 42 + 10); + for(std::size_t i = 0; i != 10; ++i) + assert(generated[i] == 42 + i); + cout << "function iterator test with stateful function object successful." << endl; + return 0; }