diff --git a/include/boost/range/detail/default_constructible_unary_fn.hpp b/include/boost/range/detail/default_constructible_unary_fn.hpp index 374ddda..9729e3c 100644 --- a/include/boost/range/detail/default_constructible_unary_fn.hpp +++ b/include/boost/range/detail/default_constructible_unary_fn.hpp @@ -32,6 +32,23 @@ public: : m_impl(source) { } + default_constructible_unary_fn_wrapper(const default_constructible_unary_fn_wrapper& source) + : m_impl(source.m_impl) + { + } + default_constructible_unary_fn_wrapper& operator=(const default_constructible_unary_fn_wrapper& source) + { + if (source.m_impl) + { + // Lambda are not copy/move assignable. + m_impl.emplace(*source.m_impl); + } + else + { + m_impl.reset(); + } + return *this; + } template R operator()(const Arg& arg) const { diff --git a/test/adaptor_test/filtered.cpp b/test/adaptor_test/filtered.cpp index 17a457f..be34872 100644 --- a/test/adaptor_test/filtered.cpp +++ b/test/adaptor_test/filtered.cpp @@ -51,6 +51,23 @@ namespace boost bool operator()( IntegerT x ) const { return x % 2 != 0; } }; + struct lambda_init + { + }; + + struct lambda + { + lambda(const lambda_init& init) {} + lambda(const lambda& rhs) {} + + template< class T1 > + bool operator()(T1) const { return false; } + + private: + lambda() {} + lambda& operator=(const lambda& rhs) { return *this; } + }; + template< class Container, class Pred > void filtered_test_impl( Container& c, Pred pred ) { @@ -86,32 +103,53 @@ namespace boost test_result2.end() ); } + template< class Rng > + void check_copy_assign(Rng r) + { + Rng r2 = r; + r2 = r; + } + template< class Container, class Pred > + void filtered_range_copy_assign(Container& c, Pred pred) + { + using namespace boost::adaptors; + check_copy_assign(c | filtered(pred)); + check_copy_assign(adaptors::filter(c, pred)); + } + + template< class Container, class Pred, class PredInit > void filtered_test_impl() { using namespace boost::assign; Container c; + PredInit init; + Pred pred(init); // test empty container - filtered_test_impl(c, Pred()); + filtered_test_impl(c, pred); // test one element c += 1; - filtered_test_impl(c, Pred()); + filtered_test_impl(c, pred); // test many elements c += 1,2,2,2,3,4,4,4,4,5,6,7,8,9,9; - filtered_test_impl(c, Pred()); + filtered_test_impl(c, pred); + + // test the range and iterator are copy assignable + filtered_range_copy_assign(c, pred); } template< class Container > void filtered_test_all_predicates() { - filtered_test_impl< Container, always_false_pred >(); - filtered_test_impl< Container, always_true_pred >(); - filtered_test_impl< Container, is_odd >(); - filtered_test_impl< Container, is_even >(); + filtered_test_impl< Container, always_false_pred, always_false_pred >(); + filtered_test_impl< Container, always_true_pred, always_true_pred >(); + filtered_test_impl< Container, is_odd, is_odd >(); + filtered_test_impl< Container, is_even, is_even >(); + filtered_test_impl< Container, lambda, lambda_init >(); } void ticket_10988_single_pass() diff --git a/test/adaptor_test/transformed.cpp b/test/adaptor_test/transformed.cpp index adadafc..9146f84 100644 --- a/test/adaptor_test/transformed.cpp +++ b/test/adaptor_test/transformed.cpp @@ -38,6 +38,22 @@ namespace boost int operator()(int x) const { return x / 2; } }; + struct lambda_init + { + }; + + struct lambda + { + lambda(const lambda_init& init) {} + lambda(const lambda& rhs) {} + + int operator()(int x) const { return x + 1; } + + private: + lambda() {} + lambda& operator=(const lambda& rhs) { return *this; } + }; + template< class Container, class TransformFn > void transformed_test_impl_core( Container& c, TransformFn fn ) { @@ -59,13 +75,29 @@ namespace boost test_result2.begin(), test_result2.end() ); } + template< class Rng > + void check_copy_assign(Rng r) + { + Rng r2 = r; + r2 = r; + } + template< class Container, class TransformFn > + void transformed_range_copy_assign(Container& c, TransformFn fn) + { + using namespace boost::adaptors; + check_copy_assign(c | transformed(fn)); + check_copy_assign(adaptors::transform(c, fn)); + } + + template< class Container, class TransformFn, class TransformFnInit > void transformed_test_fn_impl() { using namespace boost::assign; Container c; - TransformFn fn; + TransformFnInit init; + TransformFn fn( init ); // Test empty transformed_test_impl_core(c, fn); @@ -77,13 +109,17 @@ namespace boost // Test many elements c += 1,1,1,2,2,2,2,2,3,4,5,6,7,8,9; transformed_test_impl_core(c, fn); + + // test the range and iterator are copy assignable + transformed_range_copy_assign(c, fn); } template< class Container > void transformed_test_impl() { - transformed_test_fn_impl< Container, double_x >(); - transformed_test_fn_impl< Container, halve_x >(); + transformed_test_fn_impl< Container, double_x, double_x >(); + transformed_test_fn_impl< Container, halve_x, halve_x >(); + transformed_test_fn_impl< Container, lambda, lambda_init >(); } void transformed_test()