williamr@2: // (C) Copyright David Abrahams 2002. williamr@2: // (C) Copyright Jeremy Siek 2002. williamr@2: // (C) Copyright Thomas Witt 2002. williamr@2: // Distributed under the Boost Software License, Version 1.0. (See williamr@2: // accompanying file LICENSE_1_0.txt or copy at williamr@2: // http://www.boost.org/LICENSE_1_0.txt) williamr@2: #ifndef BOOST_TRANSFORM_ITERATOR_23022003THW_HPP williamr@2: #define BOOST_TRANSFORM_ITERATOR_23022003THW_HPP williamr@2: williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: williamr@2: #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) williamr@2: # include williamr@2: williamr@2: #endif williamr@2: #include williamr@2: williamr@2: williamr@2: namespace boost williamr@2: { williamr@2: template williamr@2: class transform_iterator; williamr@2: williamr@2: namespace detail williamr@2: { williamr@2: williamr@2: template williamr@2: struct function_object_result williamr@2: { williamr@2: typedef typename UnaryFunction::result_type type; williamr@2: }; williamr@2: williamr@2: #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION williamr@2: template williamr@2: struct function_object_result williamr@2: { williamr@2: typedef Return type; williamr@2: }; williamr@2: #endif williamr@2: williamr@2: // Compute the iterator_adaptor instantiation to be used for transform_iterator williamr@2: template williamr@2: struct transform_iterator_base williamr@2: { williamr@2: private: williamr@2: // By default, dereferencing the iterator yields the same as williamr@2: // the function. Do we need to adjust the way williamr@2: // function_object_result is computed for the standard williamr@2: // proposal (e.g. using Doug's result_of)? williamr@2: typedef typename ia_dflt_help< williamr@2: Reference williamr@2: , function_object_result williamr@2: >::type reference; williamr@2: williamr@2: // To get the default for Value: remove any reference on the williamr@2: // result type, but retain any constness to signal williamr@2: // non-writability. Note that if we adopt Thomas' suggestion williamr@2: // to key non-writability *only* on the Reference argument, williamr@2: // we'd need to strip constness here as well. williamr@2: typedef typename ia_dflt_help< williamr@2: Value williamr@2: , remove_reference williamr@2: >::type cv_value_type; williamr@2: williamr@2: public: williamr@2: typedef iterator_adaptor< williamr@2: transform_iterator williamr@2: , Iterator williamr@2: , cv_value_type williamr@2: , use_default // Leave the traversal category alone williamr@2: , reference williamr@2: > type; williamr@2: }; williamr@2: } williamr@2: williamr@2: template williamr@2: class transform_iterator williamr@2: : public detail::transform_iterator_base::type williamr@2: { williamr@2: typedef typename williamr@2: detail::transform_iterator_base::type williamr@2: super_t; williamr@2: williamr@2: friend class iterator_core_access; williamr@2: williamr@2: public: williamr@2: transform_iterator() { } williamr@2: williamr@2: transform_iterator(Iterator const& x, UnaryFunction f) williamr@2: : super_t(x), m_f(f) { } williamr@2: williamr@2: explicit transform_iterator(Iterator const& x) williamr@2: : super_t(x) williamr@2: { williamr@2: // Pro8 is a little too aggressive about instantiating the williamr@2: // body of this function. williamr@2: #if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) williamr@2: // don't provide this constructor if UnaryFunction is a williamr@2: // function pointer type, since it will be 0. Too dangerous. williamr@2: BOOST_STATIC_ASSERT(is_class::value); williamr@2: #endif williamr@2: } williamr@2: williamr@2: template< williamr@2: class OtherUnaryFunction williamr@2: , class OtherIterator williamr@2: , class OtherReference williamr@2: , class OtherValue> williamr@2: transform_iterator( williamr@2: transform_iterator const& t williamr@2: , typename enable_if_convertible::type* = 0 williamr@2: #if !BOOST_WORKAROUND(BOOST_MSVC, == 1310) williamr@2: , typename enable_if_convertible::type* = 0 williamr@2: #endif williamr@2: ) williamr@2: : super_t(t.base()), m_f(t.functor()) williamr@2: {} williamr@2: williamr@2: UnaryFunction functor() const williamr@2: { return m_f; } williamr@2: williamr@2: private: williamr@2: typename super_t::reference dereference() const williamr@2: { return m_f(*this->base()); } williamr@2: williamr@2: // Probably should be the initial base class so it can be williamr@2: // optimized away via EBO if it is an empty class. williamr@2: UnaryFunction m_f; williamr@2: }; williamr@2: williamr@2: template williamr@2: transform_iterator williamr@2: make_transform_iterator(Iterator it, UnaryFunction fun) williamr@2: { williamr@2: return transform_iterator(it, fun); williamr@2: } williamr@2: williamr@2: // Version which allows explicit specification of the UnaryFunction williamr@2: // type. williamr@2: // williamr@2: // This generator is not provided if UnaryFunction is a function williamr@2: // pointer type, because it's too dangerous: the default-constructed williamr@2: // function pointer in the iterator be 0, leading to a runtime williamr@2: // crash. williamr@2: template williamr@2: #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) williamr@2: typename mpl::if_< williamr@2: #else williamr@2: typename iterators::enable_if< williamr@2: #endif williamr@2: is_class // We should probably find a cheaper test than is_class<> williamr@2: , transform_iterator williamr@2: #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) williamr@2: , int[3] williamr@2: #endif williamr@2: >::type williamr@2: make_transform_iterator(Iterator it) williamr@2: { williamr@2: return transform_iterator(it, UnaryFunction()); williamr@2: } williamr@2: williamr@2: #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) williamr@2: template williamr@2: transform_iterator< Return (*)(Argument), Iterator, Return> williamr@2: make_transform_iterator(Iterator it, Return (*fun)(Argument)) williamr@2: { williamr@2: return transform_iterator(it, fun); williamr@2: } williamr@2: #endif williamr@2: williamr@2: } // namespace boost williamr@2: williamr@2: #include williamr@2: williamr@2: #endif // BOOST_TRANSFORM_ITERATOR_23022003THW_HPP