mirror of
https://github.com/boostorg/range.git
synced 2025-07-30 21:07:23 +02:00
Allow iterator copy for lambda in transformed and filtered
Lambda has no default constructor nor a copy or move assignment. range\test\adaptors.cpp is checking that produced ranges are copiable, but it is not doing so the for lambda, or lambda like objects. default_constructible_unary_fn uses an optional for default construction. I extended it to use its emplace facility to copy assign non copy assignable types. (see boost::optional 'Type Requierment': 'If T is not MoveAssignable, it is still possible to reset the value of optional<T> using function emplace():')
This commit is contained in:
@ -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<typename Arg>
|
||||
R operator()(const Arg& arg) const
|
||||
{
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
Reference in New Issue
Block a user