trac 5816 - fix any_range requiring copyable elements.

This commit is contained in:
Neil Groves
2014-03-02 15:35:50 +00:00
parent 3afac93b7f
commit 79d2a66831
3 changed files with 123 additions and 15 deletions

View File

@ -27,25 +27,40 @@ namespace boost
{ {
typedef typename mpl::if_< typedef typename mpl::if_<
typename is_reference<T>::type, typename is_reference<T>::type,
typename add_reference< typename add_const<
typename add_const< typename remove_reference<T>::type
typename remove_reference<T>::type >::type&,
>::type
>::type,
T T
>::type type; >::type type;
}; };
template<class T>
struct mutable_reference_type_generator
{
typedef typename mpl::if_<
typename mpl::and_<
typename is_const<T>::type,
typename mpl::not_<typename is_reference<T>::type>::type
>::type,
T,
typename add_reference<T>::type
>::type type;
};
template< template<
class Reference class Reference
, class Buffer , class Buffer
> >
struct any_incrementable_iterator_interface struct any_incrementable_iterator_interface
{ {
typedef Reference reference; typedef typename mutable_reference_type_generator<
Reference
>::type reference;
typedef typename const_reference_type_generator< typedef typename const_reference_type_generator<
Reference Reference
>::type const_reference; >::type const_reference;
typedef typename remove_const< typedef typename remove_const<
typename remove_reference<Reference>::type typename remove_reference<Reference>::type
>::type reference_as_value_type; >::type reference_as_value_type;
@ -87,7 +102,7 @@ namespace boost
virtual any_single_pass_iterator_interface<reference_as_value_type, Buffer>* virtual any_single_pass_iterator_interface<reference_as_value_type, Buffer>*
clone_reference_as_value(buffer_type& buffer) const = 0; clone_reference_as_value(buffer_type& buffer) const = 0;
virtual Reference dereference() const = 0; virtual reference dereference() const = 0;
virtual bool equal(const any_single_pass_iterator_interface& other) const = 0; virtual bool equal(const any_single_pass_iterator_interface& other) const = 0;
}; };

View File

@ -19,6 +19,17 @@ namespace boost
{ {
namespace range_detail namespace range_detail
{ {
template<class Reference, class T>
Reference dereference_cast(T& x)
{
return static_cast<Reference>(x);
}
template<class Reference, class T>
Reference dereference_cast(const T& x)
{
return static_cast<Reference>(const_cast<T&>(x));
}
template< template<
class WrappedIterator class WrappedIterator
, class Reference , class Reference
@ -114,7 +125,13 @@ namespace boost
{ {
struct disabler {}; struct disabler {};
BOOST_RANGE_CONCEPT_ASSERT(( SinglePassIteratorConcept<WrappedIterator> )); BOOST_RANGE_CONCEPT_ASSERT(( SinglePassIteratorConcept<WrappedIterator> ));
typedef any_single_pass_iterator_interface<
Reference,
Buffer
> base_type;
public: public:
typedef typename base_type::reference reference;
any_single_pass_iterator_wrapper() any_single_pass_iterator_wrapper()
: m_it() : m_it()
@ -178,9 +195,9 @@ namespace boost
return m_it == boost::polymorphic_downcast<const any_single_pass_iterator_wrapper*>(&other)->m_it; return m_it == boost::polymorphic_downcast<const any_single_pass_iterator_wrapper*>(&other)->m_it;
} }
virtual Reference dereference() const virtual reference dereference() const
{ {
return *m_it; return dereference_cast<reference>(*m_it);
} }
private: private:
@ -199,7 +216,14 @@ namespace boost
> >
{ {
BOOST_RANGE_CONCEPT_ASSERT(( ForwardIteratorConcept<WrappedIterator> )); BOOST_RANGE_CONCEPT_ASSERT(( ForwardIteratorConcept<WrappedIterator> ));
typedef any_forward_iterator_interface<
Reference,
Buffer
> base_type;
public: public:
typedef typename base_type::reference reference;
any_forward_iterator_wrapper() any_forward_iterator_wrapper()
: m_it() : m_it()
{} {}
@ -263,9 +287,9 @@ namespace boost
return m_it == boost::polymorphic_downcast<const any_forward_iterator_wrapper*>(&other)->m_it; return m_it == boost::polymorphic_downcast<const any_forward_iterator_wrapper*>(&other)->m_it;
} }
virtual Reference dereference() const virtual reference dereference() const
{ {
return *m_it; return dereference_cast<reference>(*m_it);
} }
private: private:
WrappedIterator m_it; WrappedIterator m_it;
@ -283,7 +307,14 @@ namespace boost
> >
{ {
BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalIteratorConcept<WrappedIterator> )); BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalIteratorConcept<WrappedIterator> ));
typedef any_bidirectional_iterator_interface<
Reference,
Buffer
> base_type;
public: public:
typedef typename base_type::reference reference;
any_bidirectional_iterator_wrapper() any_bidirectional_iterator_wrapper()
: m_it() : m_it()
{ {
@ -353,9 +384,9 @@ namespace boost
return m_it == boost::polymorphic_downcast<const any_bidirectional_iterator_wrapper*>(&other)->m_it; return m_it == boost::polymorphic_downcast<const any_bidirectional_iterator_wrapper*>(&other)->m_it;
} }
virtual Reference dereference() const virtual reference dereference() const
{ {
return *m_it; return dereference_cast<reference>(*m_it);
} }
private: private:
@ -376,7 +407,14 @@ namespace boost
> >
{ {
BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessIteratorConcept<WrappedIterator> )); BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessIteratorConcept<WrappedIterator> ));
typedef any_random_access_iterator_interface<
Reference,
Difference,
Buffer
> base_type;
public: public:
typedef typename base_type::reference reference;
typedef Difference difference_type; typedef Difference difference_type;
any_random_access_iterator_wrapper() any_random_access_iterator_wrapper()
@ -457,9 +495,9 @@ namespace boost
m_it += offset; m_it += offset;
} }
virtual Reference dereference() const virtual reference dereference() const
{ {
return *m_it; return dereference_cast<reference>(*m_it);
} }
virtual Difference distance_to(const any_random_access_iterator_interface<Reference, Difference, Buffer>& other) const virtual Difference distance_to(const any_random_access_iterator_interface<Reference, Difference, Buffer>& other) const

View File

@ -476,6 +476,60 @@ namespace boost_range_adaptor_type_erased_test
BOOST_CHECK_EQUAL( rng[i], i ); BOOST_CHECK_EQUAL( rng[i], i );
} }
} }
class dummy_interface
{
public:
virtual ~dummy_interface() { }
virtual void test() = 0;
protected:
dummy_interface() { }
private:
dummy_interface(const dummy_interface&);
void operator=(const dummy_interface&);
};
class dummy_impl
: public dummy_interface
{
public:
dummy_impl() { }
dummy_impl(const dummy_impl&) { }
dummy_impl& operator=(const dummy_impl&) { return *this; }
virtual void test() { }
};
typedef boost::any_range<
dummy_interface,
boost::random_access_traversal_tag,
dummy_interface&,
std::ptrdiff_t
> any_interface_range;
struct foo_dummy_interface_fn
{
void operator()(dummy_interface& iface)
{
iface.test();
}
};
void foo_test_dummy_interface_range(any_interface_range rng)
{
std::for_each(boost::begin(rng), boost::end(rng),
foo_dummy_interface_fn());
}
void test_type_erased_abstract()
{
std::vector<dummy_impl> v(10);
any_interface_range r(v);
foo_test_dummy_interface_range(r);
foo_test_dummy_interface_range(any_interface_range(v));
}
} }
boost::unit_test::test_suite* boost::unit_test::test_suite*
@ -492,6 +546,7 @@ init_unit_test_suite(int argc, char* argv[])
test->add( BOOST_TEST_CASE( &boost_range_adaptor_type_erased_test::test_type_erased_multiple_different_template_parameter_conversion ) ); test->add( BOOST_TEST_CASE( &boost_range_adaptor_type_erased_test::test_type_erased_multiple_different_template_parameter_conversion ) );
test->add( BOOST_TEST_CASE( &boost_range_adaptor_type_erased_test::test_type_erased_mix_values ) ); test->add( BOOST_TEST_CASE( &boost_range_adaptor_type_erased_test::test_type_erased_mix_values ) );
test->add( BOOST_TEST_CASE( &boost_range_adaptor_type_erased_test::test_type_erased_operator_brackets ) ); test->add( BOOST_TEST_CASE( &boost_range_adaptor_type_erased_test::test_type_erased_operator_brackets ) );
test->add( BOOST_TEST_CASE( &boost_range_adaptor_type_erased_test::test_type_erased_abstract ) );
return test; return test;
} }