diff --git a/include/boost/range/adaptor/replaced_if.hpp b/include/boost/range/adaptor/replaced_if.hpp old mode 100644 new mode 100755 index 83d3ec81b..b69b21f72 --- a/include/boost/range/adaptor/replaced_if.hpp +++ b/include/boost/range/adaptor/replaced_if.hpp @@ -16,22 +16,29 @@ #include #include #include -#include +#include #include #include #include #include +#include +#include +#include +#include +#include namespace boost { namespace range_detail { - template< class Pred, class Value > + template< class Pred, class Reference > class replace_value_if { public: - typedef const Value& result_type; - typedef const Value& first_argument_type; + typedef BOOST_DEDUCED_TYPENAME boost::conditional::value, + const BOOST_DEDUCED_TYPENAME boost::remove_reference::type&, + Reference>::type result_type; + typedef Reference first_argument_type; // Rationale: // required to allow the iterator to be default constructible. @@ -39,26 +46,32 @@ namespace boost { } - replace_value_if(const Pred& pred, const Value& to) + replace_value_if(const Pred& pred, const BOOST_DEDUCED_TYPENAME boost::remove_reference::type& to) : m_impl(data(pred, to)) { } - const Value& operator()(const Value& x) const + result_type operator()(Reference x) const { + #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) return m_impl->m_pred(x) ? m_impl->m_to : x; + #else + return m_impl->m_pred(x) ? m_impl->m_to : boost::forward(x); + #endif } private: + + struct data { - data(const Pred& p, const Value& t) + data(const Pred& p, const BOOST_DEDUCED_TYPENAME boost::remove_reference::type& t) : m_pred(p), m_to(t) { } Pred m_pred; - Value m_to; + BOOST_DEDUCED_TYPENAME boost::remove_const::type>::type m_to; }; boost::optional m_impl; }; @@ -67,21 +80,21 @@ namespace boost class replaced_if_range : public boost::iterator_range< boost::transform_iterator< - replace_value_if< Pred, BOOST_DEDUCED_TYPENAME range_value::type >, + replace_value_if< Pred, BOOST_DEDUCED_TYPENAME range_reference::type >, BOOST_DEDUCED_TYPENAME range_iterator::type > > { private: - typedef replace_value_if< Pred, BOOST_DEDUCED_TYPENAME range_value::type > Fn; + typedef replace_value_if< Pred, BOOST_DEDUCED_TYPENAME range_reference::type > Fn; typedef boost::iterator_range< boost::transform_iterator< - replace_value_if< Pred, BOOST_DEDUCED_TYPENAME range_value::type >, + replace_value_if< Pred, BOOST_DEDUCED_TYPENAME range_reference::type >, BOOST_DEDUCED_TYPENAME range_iterator::type > > base_t; public: - typedef BOOST_DEDUCED_TYPENAME range_value::type value_type; + typedef BOOST_DEDUCED_TYPENAME range_reference::type reference_type; - replaced_if_range( R& r, const Pred& pred, value_type to ) + replaced_if_range( R& r, const Pred& pred, const BOOST_DEDUCED_TYPENAME boost::remove_reference::type& to ) : base_t( make_transform_iterator( boost::begin(r), Fn(pred, to) ), make_transform_iterator( boost::end(r), Fn(pred, to) ) ) { } diff --git a/test/adaptor_test/replaced_if.cpp b/test/adaptor_test/replaced_if.cpp old mode 100644 new mode 100755 index 0bf227f31..59b2b4ed2 --- a/test/adaptor_test/replaced_if.cpp +++ b/test/adaptor_test/replaced_if.cpp @@ -9,6 +9,8 @@ // For more information, see http://www.boost.org/libs/range/ // #include +#include +#include #include #include @@ -30,6 +32,13 @@ namespace boost bool operator()(int x) const { return x == 1; } }; + struct minus_one + { + typedef int result_type; + typedef int argument_type; + int operator()(int x) const {return x - 1; } + }; + template< class Container > void replaced_if_test_impl( Container& c ) { @@ -81,6 +90,33 @@ namespace boost replaced_if_test_impl< std::set< int > >(); replaced_if_test_impl< std::multiset< int > >(); } + + void replaced_if_combined_with_transformed_test() + { + using namespace boost::adaptors; + using namespace boost::assign; + + minus_one unary_fn; + if_value_is_one pred; + + std::vector input; + + input += 4,3,2,1; + + const int replacement_value = 7; + + std::vector reference; + + std::vector temp; + boost::push_back(temp, input | transformed(unary_fn)); + boost::push_back(reference, temp | replaced_if(pred, replacement_value)); + + std::vector test_result = boost::copy_range< std::vector >(input | transformed(unary_fn) + | replaced_if(pred, replacement_value)); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test_result.begin(), test_result.end() ); + } } } @@ -91,6 +127,7 @@ init_unit_test_suite(int argc, char* argv[]) = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.replaced_if" ); test->add( BOOST_TEST_CASE( &boost::replaced_if_test ) ); + test->add( BOOST_TEST_CASE( &boost::replaced_if_combined_with_transformed_test ) ); return test; }