From d469568de76780fbc8669f5b555a83baab2be47b Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Thu, 10 Jun 2010 05:59:46 +0000 Subject: [PATCH] function_input_iterator fixes from Dean Michael Berris [SVN r62710] --- .../iterator/function_input_iterator.hpp | 106 ++++++++++++++++-- test/Jamfile.v2 | 1 + test/function_input_iterator_test.cpp | 70 ++++++++++++ 3 files changed, 167 insertions(+), 10 deletions(-) create mode 100644 test/function_input_iterator_test.cpp diff --git a/include/boost/iterator/function_input_iterator.hpp b/include/boost/iterator/function_input_iterator.hpp index b4537cb..8f1df68 100644 --- a/include/boost/iterator/function_input_iterator.hpp +++ b/include/boost/iterator/function_input_iterator.hpp @@ -7,23 +7,29 @@ #ifndef BOOST_FUNCTION_INPUT_ITERATOR #define BOOST_FUNCTION_INPUT_ITERATOR +#include +#include +#include +#include #include namespace boost { - template + namespace impl { + + template class function_input_iterator - : public iterator_facade< + : public iterator_facade< function_input_iterator, typename Function::result_type, single_pass_traversal_tag, typename Function::result_type const & > - { + { public: function_input_iterator() {} - function_input_iterator(Function * f_, Input state_ = Input()) - : f(f_), state(state_), value((*f)()) {} + function_input_iterator(Function & f_, Input state_ = Input()) + : f(&f_), state(state_), value((*f)()) {} void increment() { value = (*f)(); @@ -31,8 +37,8 @@ namespace boost { } typename Function::result_type const & - dereference() const { - return value; + dereference() const { + return value; } bool equal(function_input_iterator const & other) const { @@ -43,13 +49,93 @@ namespace boost { Function * f; Input state; typename Function::result_type value; + }; + + template + class function_pointer_input_iterator + : public iterator_facade< + function_pointer_input_iterator, + typename function_types::result_type::type, + single_pass_traversal_tag, + typename function_types::result_type::type const & + > + { + public: + function_pointer_input_iterator() {} + function_pointer_input_iterator(Function &f_, Input state_ = Input()) + : f(f_), state(state_), value((*f)()) + {} + + void increment() { + value = (*f)(); + ++state; + } + + typename function_types::result_type::type const & + dereference() const { + return value; + } + + bool equal(function_pointer_input_iterator const & other) const { + return f == other.f && state == other.state; + } + + private: + Function f; + Input state; + typename function_types::result_type::type value; + }; + + template + class function_reference_input_iterator + : public function_pointer_input_iterator + { + public: + function_reference_input_iterator(Function & f_, Input state_ = Input()) + : function_pointer_input_iterator(&f_, state_) + {} + }; + + } // namespace impl + + template + class function_input_iterator + : public mpl::if_< + function_types::is_function_pointer, + impl::function_pointer_input_iterator, + typename mpl::if_< + function_types::is_function_reference, + impl::function_reference_input_iterator, + impl::function_input_iterator + >::type + >::type + { + typedef typename mpl::if_< + function_types::is_function_pointer, + impl::function_pointer_input_iterator, + typename mpl::if_< + function_types::is_function_reference, + impl::function_reference_input_iterator, + impl::function_input_iterator + >::type + >::type base_type; + public: + function_input_iterator(Function & f, Input i) + : base_type(f, i) {} }; template inline function_input_iterator - make_function_input_iterator(Function & f, Input state) { - typedef function_input_iterator result_t; - return result_t(&f, state); + make_function_input_iterator(Function & f, Input state) { + typedef function_input_iterator result_t; + return result_t(f, state); + } + + template + inline function_input_iterator + make_function_input_iterator(Function * f, Input state) { + typedef function_input_iterator result_t; + return result_t(f, state); } struct infinite { diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 8503b2b..023a826 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -43,5 +43,6 @@ test-suite iterator [ run iterator_traits_test.cpp ] [ run permutation_iterator_test.cpp : : : # on ] + [ run function_input_iterator_test.cpp ] ; diff --git a/test/function_input_iterator_test.cpp b/test/function_input_iterator_test.cpp new file mode 100644 index 0000000..0fea9c1 --- /dev/null +++ b/test/function_input_iterator_test.cpp @@ -0,0 +1,70 @@ +// Copyright 2010 (c) Dean Michael Berris +// 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) + +#include +#include +#include +#include +#include +#include + +struct ones { + typedef int result_type; + result_type operator() () { + return 1; + } +}; + +int ones_function () { + return 1; +} + +using namespace std; + +int main(int argc, char * argv[]) +{ + // test the iterator with function objects + ones ones_generator; + vector values(10); + generate(values.begin(), values.end(), ones()); + + vector generated; + copy( + boost::make_function_input_iterator(ones_generator, 0), + boost::make_function_input_iterator(ones_generator, 10), + back_inserter(generated) + ); + + assert(values.size() == generated.size()); + assert(equal(values.begin(), values.end(), generated.begin())); + cout << "function iterator test with function objects successful." << endl; + + // test the iterator with normal functions + vector().swap(generated); + copy( + boost::make_function_input_iterator(&ones_function, 0), + boost::make_function_input_iterator(&ones_function, 10), + back_inserter(generated) + ); + + assert(values.size() == generated.size()); + assert(equal(values.begin(), values.end(), generated.begin())); + cout << "function iterator test with pointer to function successful." << endl; + + // test the iterator with a reference to a function + vector().swap(generated); + copy( + boost::make_function_input_iterator(ones_function, 0), + boost::make_function_input_iterator(ones_function, 10), + back_inserter(generated) + ); + + assert(values.size() == generated.size()); + assert(equal(values.begin(), values.end(), generated.begin())); + cout << "function iterator test with reference to function successful." << endl; + + return 0; +} +