Skip to content

Commit 365f6e1

Browse files
committed
Fixing non-reference base_t::reference case for replaced_if adaptor
1 parent 72e2a44 commit 365f6e1

File tree

2 files changed

+63
-13
lines changed

2 files changed

+63
-13
lines changed

include/boost/range/adaptor/replaced_if.hpp

100644100755
Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,49 +16,62 @@
1616
#include <boost/range/iterator_range.hpp>
1717
#include <boost/range/begin.hpp>
1818
#include <boost/range/end.hpp>
19-
#include <boost/range/value_type.hpp>
19+
#include <boost/range/reference.hpp>
2020
#include <boost/range/concepts.hpp>
2121
#include <boost/iterator/iterator_adaptor.hpp>
2222
#include <boost/iterator/transform_iterator.hpp>
2323
#include <boost/optional/optional.hpp>
24+
#include <boost/move/utility_core.hpp>
25+
#include <boost/type_traits/remove_reference.hpp>
26+
#include <boost/type_traits/remove_const.hpp>
27+
#include <boost/type_traits/is_reference.hpp>
28+
#include <boost/type_traits/conditional.hpp>
2429

2530
namespace boost
2631
{
2732
namespace range_detail
2833
{
29-
template< class Pred, class Value >
34+
template< class Pred, class Reference >
3035
class replace_value_if
3136
{
3237
public:
33-
typedef const Value& result_type;
34-
typedef const Value& first_argument_type;
38+
typedef BOOST_DEDUCED_TYPENAME boost::conditional<boost::is_reference<Reference>::value,
39+
const BOOST_DEDUCED_TYPENAME boost::remove_reference<Reference>::type&,
40+
Reference>::type result_type;
41+
typedef Reference first_argument_type;
3542

3643
// Rationale:
3744
// required to allow the iterator to be default constructible.
3845
replace_value_if()
3946
{
4047
}
4148

42-
replace_value_if(const Pred& pred, const Value& to)
49+
replace_value_if(const Pred& pred, const BOOST_DEDUCED_TYPENAME boost::remove_reference<Reference>::type& to)
4350
: m_impl(data(pred, to))
4451
{
4552
}
4653

47-
const Value& operator()(const Value& x) const
54+
result_type operator()(Reference x) const
4855
{
56+
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
4957
return m_impl->m_pred(x) ? m_impl->m_to : x;
58+
#else
59+
return m_impl->m_pred(x) ? m_impl->m_to : boost::forward<Reference>(x);
60+
#endif
5061
}
5162

5263
private:
64+
65+
5366
struct data
5467
{
55-
data(const Pred& p, const Value& t)
68+
data(const Pred& p, const BOOST_DEDUCED_TYPENAME boost::remove_reference<Reference>::type& t)
5669
: m_pred(p), m_to(t)
5770
{
5871
}
5972

6073
Pred m_pred;
61-
Value m_to;
74+
BOOST_DEDUCED_TYPENAME boost::remove_const<BOOST_DEDUCED_TYPENAME boost::remove_reference<Reference>::type>::type m_to;
6275
};
6376
boost::optional<data> m_impl;
6477
};
@@ -67,21 +80,21 @@ namespace boost
6780
class replaced_if_range :
6881
public boost::iterator_range<
6982
boost::transform_iterator<
70-
replace_value_if< Pred, BOOST_DEDUCED_TYPENAME range_value<R>::type >,
83+
replace_value_if< Pred, BOOST_DEDUCED_TYPENAME range_reference<R>::type >,
7184
BOOST_DEDUCED_TYPENAME range_iterator<R>::type > >
7285
{
7386
private:
74-
typedef replace_value_if< Pred, BOOST_DEDUCED_TYPENAME range_value<R>::type > Fn;
87+
typedef replace_value_if< Pred, BOOST_DEDUCED_TYPENAME range_reference<R>::type > Fn;
7588

7689
typedef boost::iterator_range<
7790
boost::transform_iterator<
78-
replace_value_if< Pred, BOOST_DEDUCED_TYPENAME range_value<R>::type >,
91+
replace_value_if< Pred, BOOST_DEDUCED_TYPENAME range_reference<R>::type >,
7992
BOOST_DEDUCED_TYPENAME range_iterator<R>::type > > base_t;
8093

8194
public:
82-
typedef BOOST_DEDUCED_TYPENAME range_value<R>::type value_type;
95+
typedef BOOST_DEDUCED_TYPENAME range_reference<R>::type reference_type;
8396

84-
replaced_if_range( R& r, const Pred& pred, value_type to )
97+
replaced_if_range( R& r, const Pred& pred, const BOOST_DEDUCED_TYPENAME boost::remove_reference<reference_type>::type& to )
8598
: base_t( make_transform_iterator( boost::begin(r), Fn(pred, to) ),
8699
make_transform_iterator( boost::end(r), Fn(pred, to) ) )
87100
{ }

test/adaptor_test/replaced_if.cpp

100644100755
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
// For more information, see http://www.boost.org/libs/range/
1010
//
1111
#include <boost/range/adaptor/replaced_if.hpp>
12+
#include <boost/range/adaptor/transformed.hpp>
13+
#include <boost/range/iterator_range.hpp>
1214

1315
#include <boost/test/test_tools.hpp>
1416
#include <boost/test/unit_test.hpp>
@@ -30,6 +32,13 @@ namespace boost
3032
bool operator()(int x) const { return x == 1; }
3133
};
3234

35+
struct minus_one
36+
{
37+
typedef int result_type;
38+
typedef int argument_type;
39+
int operator()(int x) const {return x - 1; }
40+
};
41+
3342
template< class Container >
3443
void replaced_if_test_impl( Container& c )
3544
{
@@ -81,6 +90,33 @@ namespace boost
8190
replaced_if_test_impl< std::set< int > >();
8291
replaced_if_test_impl< std::multiset< int > >();
8392
}
93+
94+
void replaced_if_combined_with_transformed_test()
95+
{
96+
using namespace boost::adaptors;
97+
using namespace boost::assign;
98+
99+
minus_one unary_fn;
100+
if_value_is_one pred;
101+
102+
std::vector<int> input;
103+
104+
input += 4,3,2,1;
105+
106+
const int replacement_value = 7;
107+
108+
std::vector<int> reference;
109+
110+
std::vector<int> temp;
111+
boost::push_back(temp, input | transformed(unary_fn));
112+
boost::push_back(reference, temp | replaced_if(pred, replacement_value));
113+
114+
std::vector<int> test_result = boost::copy_range< std::vector<int> >(input | transformed(unary_fn)
115+
| replaced_if(pred, replacement_value));
116+
117+
BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(),
118+
test_result.begin(), test_result.end() );
119+
}
84120
}
85121
}
86122

@@ -91,6 +127,7 @@ init_unit_test_suite(int argc, char* argv[])
91127
= BOOST_TEST_SUITE( "RangeTestSuite.adaptor.replaced_if" );
92128

93129
test->add( BOOST_TEST_CASE( &boost::replaced_if_test ) );
130+
test->add( BOOST_TEST_CASE( &boost::replaced_if_combined_with_transformed_test ) );
94131

95132
return test;
96133
}

0 commit comments

Comments
 (0)