diff --git a/include/boost/iterator/transform_iterator.hpp b/include/boost/iterator/transform_iterator.hpp index 102f69b..3400134 100644 --- a/include/boost/iterator/transform_iterator.hpp +++ b/include/boost/iterator/transform_iterator.hpp @@ -31,6 +31,20 @@ namespace boost namespace detail { + template + struct result + { + typedef typename UnaryFunction::result_type type; + }; + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct result + { + typedef Return type; + }; +#endif + // Given the transform iterator's transformation and iterator, this // is the type used as its traits. template @@ -43,9 +57,17 @@ namespace boost BOOST_STATIC_ASSERT((is_tag< readable_iterator_tag, typename access_category::type >::value)); #endif - typedef typename UnaryFunction::result_type result_type; + typedef typename mpl::apply_if< + is_same< Reference, use_default > + , result + , mpl::identity + >::type result_type; - typedef typename remove_reference< result_type >::type cv_value_type; + typedef typename mpl::if_< + is_same< Value, use_default > + , typename remove_reference< result_type >::type + , Value + >::type cv_value_type; typedef typename mpl::if_< is_reference< result_type > @@ -64,7 +86,7 @@ namespace boost public: typedef iterator_adaptor< - transform_iterator + transform_iterator , Iterator , cv_value_type , iterator_tag< @@ -95,8 +117,8 @@ namespace boost template transform_iterator( - transform_iterator const& t - , typename enable_if_convertible::type* = 0 + transform_iterator const& t + , typename enable_if_convertible::type* = 0 ) : super_t(t.base()), m_f(t.functor()) {} @@ -112,20 +134,20 @@ namespace boost UnaryFunction m_f; }; - template - transform_iterator make_transform_iterator(Iterator it, UnaryFunctionObject fun) + template + transform_iterator make_transform_iterator(Iterator it, UnaryFunction fun) { - return transform_iterator(it, fun); + return transform_iterator(it, fun); } +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template - transform_iterator< function1, Iterator> + transform_iterator< Return (*)(Argument), Iterator, Return> make_transform_iterator(Iterator it, Return (*fun)(Argument)) { - typedef function1 function_t; - - return transform_iterator(it, function_t(fun)); + return transform_iterator(it, fun); } +#endif } // namespace boost diff --git a/test/transform_iterator_test.cpp b/test/transform_iterator_test.cpp index 8d6a55e..fe694b5 100644 --- a/test/transform_iterator_test.cpp +++ b/test/transform_iterator_test.cpp @@ -43,8 +43,6 @@ namespace boost { namespace detail #endif struct mult_functor { - typedef int result_type; - typedef int argument_type; // Functors used with transform_iterator must be // DefaultConstructible, as the transform_iterator must be // DefaultConstructible to satisfy the requirements for @@ -55,6 +53,19 @@ struct mult_functor { int a; }; +struct adaptable_mult_functor + : mult_functor +{ + typedef int result_type; + typedef int argument_type; + // Functors used with transform_iterator must be + // DefaultConstructible, as the transform_iterator must be + // DefaultConstructible to satisfy the requirements for + // TrivialIterator. + adaptable_mult_functor() { } + adaptable_mult_functor(int aa) : mult_functor(aa) { } +}; + struct select_first { @@ -108,8 +119,8 @@ main() // Concept checks { - typedef boost::transform_iterator iter_t; - typedef boost::transform_iterator c_iter_t; + typedef boost::transform_iterator iter_t; + typedef boost::transform_iterator c_iter_t; boost::function_requires< boost_concepts::InteroperableConcept >(); } @@ -124,7 +135,25 @@ main() for (int k2 = 0; k2 < N; ++k2) x[k2] = x[k2] * 2; - typedef boost::transform_iterator iter_t; + typedef boost::transform_iterator iter_t; + iter_t i(y, adaptable_mult_functor(2)); + boost::input_iterator_test(i, x[0], x[1]); + boost::input_iterator_test(iter_t(&y[0], adaptable_mult_functor(2)), x[0], x[1]); + + boost::random_access_readable_iterator_test(i, N, x); + } + + // Test transform_iterator non adaptable functor + { + int x[N], y[N]; + for (int k = 0; k < N; ++k) + x[k] = k; + std::copy(x, x + N, y); + + for (int k2 = 0; k2 < N; ++k2) + x[k2] = x[k2] * 2; + + typedef boost::transform_iterator iter_t; iter_t i(y, mult_functor(2)); boost::input_iterator_test(i, x[0], x[1]); boost::input_iterator_test(iter_t(&y[0], mult_functor(2)), x[0], x[1]); @@ -132,6 +161,27 @@ main() boost::random_access_readable_iterator_test(i, N, x); } + // Test transform_iterator default argument handling + { + { + typedef boost::transform_iterator iter_t; + BOOST_STATIC_ASSERT((boost::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); + } + + { + typedef boost::transform_iterator iter_t; + BOOST_STATIC_ASSERT((boost::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); + } + + { + typedef boost::transform_iterator iter_t; + BOOST_STATIC_ASSERT((boost::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); + } + } + // Test transform_iterator with function pointers { int x[N], y[N];