[boost][range] - Updated begin/end to be protected against accidental ADL to improve compatibility with C++0x. Added any_range which adds type erasure support. Added a type_erased adaptor to utilise the any_range. Implemented the any_iterator using a small buffer optimization to avoid heap usage.

[SVN r67541]
This commit is contained in:
Neil Groves
2011-01-01 16:46:32 +00:00
parent c506d2537f
commit 55fd3ca5b2
122 changed files with 4087 additions and 594 deletions
+4
View File
@@ -59,6 +59,8 @@ test-suite range :
[ range-test adaptor_test/sliced_example ]
[ range-test adaptor_test/strided_example ]
[ range-test adaptor_test/transformed_example ]
[ range-test adaptor_test/type_erased ]
[ range-test adaptor_test/type_erased_example ]
[ range-test adaptor_test/uniqued_example ]
[ range-test algorithm_test/adjacent_find ]
[ range-test algorithm_test/binary_search ]
@@ -131,11 +133,13 @@ test-suite range :
[ range-test algorithm_example ]
[ range-test array ]
# [ range-test atl : <include>$(VC71_ROOT)/atlmfc/include ]
[ range-test begin ]
[ range-test combine ]
[ range-test compat2 ]
[ range-test compat3 ]
[ range-test const_ranges ]
[ range-test counting_range ]
[ range-test end ]
[ range-test extension_mechanism ]
[ range-test extension_size ]
[ range-test has_range_iterator ]
+487
View File
@@ -0,0 +1,487 @@
// Boost.Range library
//
// Copyright Neil Groves 2010. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/range/adaptor/type_erased.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/range/algorithm_ext.hpp>
#include <boost/range/algorithm/fill.hpp>
#include <boost/assign.hpp>
#include <boost/array.hpp>
#include <algorithm>
#include <list>
#include <set>
#include <vector>
namespace boost_range_adaptor_type_erased_test
{
namespace
{
class MockType
{
public:
explicit MockType(int x)
: m_x(x) {}
int get() const { return m_x; }
bool operator==(const MockType& other) const
{
return m_x == other.m_x;
}
bool operator!=(const MockType& other) const
{
return m_x != other.m_x;
}
private:
int m_x;
};
std::ostream& operator<<(std::ostream& out, const MockType& obj)
{
out << obj.get();
return out;
}
template<class Container>
void test_type_erased_impl(Container& c)
{
using namespace boost::adaptors;
typedef typename boost::range_value<Container>::type value_type;
typedef typename boost::adaptors::type_erased<> type_erased_t;
std::vector<value_type> output;
boost::push_back(output, boost::adaptors::type_erase(c, type_erased_t()));
BOOST_CHECK_EQUAL_COLLECTIONS( output.begin(), output.end(),
c.begin(), c.end() );
output.clear();
boost::push_back(output, c | type_erased_t());
BOOST_CHECK_EQUAL_COLLECTIONS( output.begin(), output.end(),
c.begin(), c.end() );
}
template<class Container>
void test_const_and_mutable(Container& c)
{
test_type_erased_impl(c);
const Container& const_c = c;
test_type_erased_impl(const_c);
}
template<class Container>
void test_driver()
{
using namespace boost::assign;
typedef typename boost::range_value<Container>::type value_type;
Container c;
test_const_and_mutable(c);
c += value_type(1);
test_const_and_mutable(c);
c += value_type(2);
test_const_and_mutable(c);
}
void test_type_erased()
{
test_driver< std::list<int> >();
test_driver< std::vector<int> >();
test_driver< std::list<MockType> >();
test_driver< std::vector<MockType> >();
}
template<
class Traversal
, class Container
>
void test_writeable(Container&, boost::single_pass_traversal_tag)
{}
template<
class Traversal
, class Container
>
void test_writeable(Container& source, boost::forward_traversal_tag)
{
using namespace boost::adaptors;
typedef typename boost::range_value<Container>::type value_type;
typedef typename boost::range_difference<Container>::type difference_type;
typedef typename boost::range_reference<Container>::type mutable_reference_type;
typedef boost::any_range<
value_type
, Traversal
, mutable_reference_type
, difference_type
> mutable_any_range;
mutable_any_range r = source | boost::adaptors::type_erased<>();
std::vector<value_type> output_test;
boost::fill(r, value_type(1));
BOOST_CHECK_EQUAL( boost::distance(r), boost::distance(source) );
std::vector<value_type> reference_output(source.size(), value_type(1));
BOOST_CHECK_EQUAL_COLLECTIONS( reference_output.begin(), reference_output.end(),
r.begin(), r.end() );
}
template<
class Container
, class Traversal
, class Buffer
>
void test_type_erased_impl()
{
using namespace boost::adaptors;
typedef Buffer buffer_type;
typedef typename boost::range_value<Container>::type value_type;
typedef typename boost::any_range_type_generator<
Container
, boost::use_default
, Traversal
, boost::use_default
, boost::use_default
, Buffer
>::type mutable_any_range;
typedef typename boost::any_range_type_generator<
const Container
, boost::use_default
, Traversal
, boost::use_default
, boost::use_default
, Buffer
>::type const_any_range;
typedef boost::adaptors::type_erased<
boost::use_default
, Traversal
, boost::use_default
, boost::use_default
, Buffer
> type_erased_t;
type_erased_t type_erased_ex;
Container source;
for (int i = 0; i < 100; ++i)
source.push_back(value_type(i));
mutable_any_range r(source);
BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
r.begin(), r.end() );
r = mutable_any_range();
BOOST_CHECK_EQUAL( r.empty(), true );
r = source | type_erased_ex;
BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
r.begin(), r.end() );
r = mutable_any_range();
r = boost::adaptors::type_erase(source, type_erased_ex);
BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
r.begin(), r.end() );
r = mutable_any_range();
test_writeable<Traversal>(source, Traversal());
// convert and construct a const any_range from a mutable source
// range
const_any_range cr(source);
BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
cr.begin(), cr.end() );
// assign an empty range and ensure that this correctly results
// in an empty range. This is important for the validity of
// the rest of the tests.
cr = const_any_range();
BOOST_CHECK_EQUAL( cr.empty(), true );
// Test the pipe type_erased adaptor from a constant source
// range to a constant any_range
const Container& const_source = source;
cr = const_any_range();
cr = const_source | type_erased_ex;
BOOST_CHECK_EQUAL_COLLECTIONS( const_source.begin(), const_source.end(),
cr.begin(), cr.end() );
// Test the pipe type erased adaptor from a mutable source
// range to a constant any_range
cr = const_any_range();
cr = source | type_erased_ex;
BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(),
cr.begin(), cr.end() );
// Use the function form of the type_erase adaptor from a constant
// source range
cr = const_any_range();
cr = boost::adaptors::type_erase(const_source, type_erased_ex);
BOOST_CHECK_EQUAL_COLLECTIONS( const_source.begin(), const_source.end(),
cr.begin(), cr.end() );
// Assignment from mutable to const...
cr = const_any_range();
cr = r;
BOOST_CHECK_EQUAL_COLLECTIONS( cr.begin(), cr.end(),
r.begin(), r.end() );
// Converting copy from mutable to const...
cr = const_any_range();
cr = const_any_range(r);
BOOST_CHECK_EQUAL_COLLECTIONS( cr.begin(), cr.end(),
r.begin(), r.end() );
}
template<
class Container
, class Traversal
, class Buffer
>
class test_type_erased_impl_fn
{
public:
typedef void result_type;
void operator()()
{
test_type_erased_impl< Container, Traversal, Buffer >();
}
};
template<
class Container
, class Traversal
>
void test_type_erased_exercise_buffer_types()
{
using boost::any_iterator_default_buffer;
using boost::any_iterator_buffer;
using boost::any_iterator_heap_only_buffer;
using boost::any_iterator_stack_only_buffer;
test_type_erased_impl_fn< Container, Traversal, any_iterator_default_buffer >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_heap_only_buffer >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<1> >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<2> >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<4> >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<8> >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<16> >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<32> >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<64> >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<128> >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<4096> >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<16384> >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_stack_only_buffer<128> >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_stack_only_buffer<4096> >()();
test_type_erased_impl_fn< Container, Traversal, any_iterator_stack_only_buffer<16384> >()();
}
void test_type_erased_single_pass()
{
test_type_erased_exercise_buffer_types< std::list<int>, boost::single_pass_traversal_tag >();
test_type_erased_exercise_buffer_types< std::deque<int>, boost::single_pass_traversal_tag >();
test_type_erased_exercise_buffer_types< std::vector<int>, boost::single_pass_traversal_tag >();
test_type_erased_exercise_buffer_types< std::list<MockType>, boost::single_pass_traversal_tag >();
test_type_erased_exercise_buffer_types< std::deque<MockType>, boost::single_pass_traversal_tag >();
test_type_erased_exercise_buffer_types< std::vector<MockType>, boost::single_pass_traversal_tag >();
}
void test_type_erased_forward()
{
test_type_erased_exercise_buffer_types< std::list<int>, boost::forward_traversal_tag >();
test_type_erased_exercise_buffer_types< std::deque<int>, boost::forward_traversal_tag >();
test_type_erased_exercise_buffer_types< std::vector<int>, boost::forward_traversal_tag >();
test_type_erased_exercise_buffer_types< std::list<MockType>, boost::forward_traversal_tag >();
test_type_erased_exercise_buffer_types< std::deque<MockType>, boost::forward_traversal_tag >();
test_type_erased_exercise_buffer_types< std::vector<MockType>, boost::forward_traversal_tag >();
}
void test_type_erased_bidirectional()
{
test_type_erased_exercise_buffer_types< std::list<int>, boost::bidirectional_traversal_tag >();
test_type_erased_exercise_buffer_types< std::deque<int>, boost::bidirectional_traversal_tag >();
test_type_erased_exercise_buffer_types< std::vector<int>, boost::bidirectional_traversal_tag >();
test_type_erased_exercise_buffer_types< std::list<MockType>, boost::bidirectional_traversal_tag >();
test_type_erased_exercise_buffer_types< std::deque<MockType>, boost::bidirectional_traversal_tag >();
test_type_erased_exercise_buffer_types< std::vector<MockType>, boost::bidirectional_traversal_tag >();
}
void test_type_erased_random_access()
{
test_type_erased_exercise_buffer_types< std::deque<int>, boost::random_access_traversal_tag >();
test_type_erased_exercise_buffer_types< std::vector<int>, boost::random_access_traversal_tag >();
test_type_erased_exercise_buffer_types< std::deque<MockType>, boost::random_access_traversal_tag >();
test_type_erased_exercise_buffer_types< std::vector<MockType>, boost::random_access_traversal_tag >();
}
void test_type_erased_multiple_different_template_parameter_conversion()
{
typedef boost::any_range<
int
, boost::random_access_traversal_tag
, int&
, std::ptrdiff_t
> source_range_type;
typedef boost::any_range<
int
, boost::single_pass_traversal_tag
, const int&
, std::ptrdiff_t
> target_range_type;
source_range_type source;
// Converting via construction
target_range_type t1(source);
// Converting via assignment
target_range_type t2;
t2 = source;
// Converting via construction to a type with a reference type
// that is a value
typedef boost::any_range<
int
, boost::single_pass_traversal_tag
, int
, std::ptrdiff_t
> target_range2_type;
target_range2_type t3(source);
target_range2_type t4;
t4 = source;
}
template<
class Traversal
, class ValueType
, class SourceValueType
, class SourceReference
, class TargetValueType
, class TargetReference
>
void test_type_erased_mix_values_impl()
{
typedef std::vector< ValueType > Container;
typedef typename boost::any_range_type_generator<
Container
, SourceValueType
, Traversal
, SourceReference
>::type source_type;
typedef typename boost::any_range_type_generator<
Container
, TargetValueType
, Traversal
, TargetReference
>::type target_type;
Container test_data;
for (int i = 0; i < 10; ++i)
test_data.push_back(i);
const source_type source_data(test_data);
target_type t1(source_data);
BOOST_CHECK_EQUAL_COLLECTIONS( source_data.begin(), source_data.end(),
t1.begin(), t1.end() );
target_type t2;
t2 = source_data;
BOOST_CHECK_EQUAL_COLLECTIONS( source_data.begin(), source_data.end(),
t2.begin(), t2.end() );
}
class MockInt
{
public:
MockInt() : m_value() {}
MockInt(int x) : m_value(x) {}
operator int() const { return m_value; }
private:
int m_value;
};
template<class Traversal>
void test_type_erased_mix_values_driver()
{
test_type_erased_mix_values_impl< Traversal, int, char, const int&, short, const int& >();
test_type_erased_mix_values_impl< Traversal, int, int*, const int&, char, const int& >();
test_type_erased_mix_values_impl< Traversal, MockInt, char, const MockInt&, short, const MockInt& >();
// In fact value type should have no effect in the eligibility
// for conversion, hence we should be able to convert it
// completely backwards!
test_type_erased_mix_values_impl< Traversal, int, short, const int&, char, const int& >();
test_type_erased_mix_values_impl< Traversal, int, char, const int&, int*, const int& >();
}
void test_type_erased_mix_values()
{
test_type_erased_mix_values_driver< boost::single_pass_traversal_tag >();
test_type_erased_mix_values_driver< boost::forward_traversal_tag >();
test_type_erased_mix_values_driver< boost::bidirectional_traversal_tag >();
test_type_erased_mix_values_driver< boost::random_access_traversal_tag >();
}
void test_type_erased_operator_brackets()
{
typedef boost::adaptors::type_erased<> type_erased_t;
std::vector<int> c;
for (int i = 0; i < 10; ++i)
c.push_back(i);
for (int i = 0; i < 10; ++i)
{
BOOST_CHECK_EQUAL( (c | type_erased_t())[i], i );
}
}
}
}
boost::unit_test::test_suite*
init_unit_test_suite(int argc, char* argv[])
{
boost::unit_test::test_suite* test
= BOOST_TEST_SUITE( "RangeTestSuite.adaptor.type_erased" );
test->add( BOOST_TEST_CASE( &boost_range_adaptor_type_erased_test::test_type_erased ) );
test->add( BOOST_TEST_CASE( &boost_range_adaptor_type_erased_test::test_type_erased_single_pass ) );
test->add( BOOST_TEST_CASE( &boost_range_adaptor_type_erased_test::test_type_erased_forward ) );
test->add( BOOST_TEST_CASE( &boost_range_adaptor_type_erased_test::test_type_erased_bidirectional ) );
test->add( BOOST_TEST_CASE( &boost_range_adaptor_type_erased_test::test_type_erased_random_access ) );
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_operator_brackets ) );
return test;
}
+115
View File
@@ -0,0 +1,115 @@
// Boost.Range library
//
// Copyright Neil Groves 2010. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// For more information, see http://www.boost.org/libs/range/
//
#include <boost/range/adaptor/type_erased.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/assign.hpp>
#include <boost/foreach.hpp>
#include <algorithm>
#include <iostream>
#include <list>
#include <vector>
#include <boost/test/test_tools.hpp>
#include <boost/test/unit_test.hpp>
namespace
{
namespace boost_range_test
{
namespace type_erased_example
{
// The client interface from an OO perspective merely requires a sequence
// of integers that can be forward traversed
typedef boost::any_range<
int
, boost::forward_traversal_tag
, int
, std::ptrdiff_t
> integer_range;
namespace server
{
void display_integers(const integer_range& rng)
{
boost::copy(rng,
std::ostream_iterator<int>(std::cout, ","));
std::cout << std::endl;
}
}
namespace client
{
void run()
{
using namespace boost::assign;
using namespace boost::adaptors;
// Under most conditions one would simply use an appropriate
// any_range as a function parameter. The type_erased adaptor
// is often superfluous. However because the type_erased
// adaptor is applied to a range, we can use default template
// arguments that are generated in conjunction with the
// range type to which we are applying the adaptor.
std::vector<int> input;
input += 1,2,3,4,5;
// Note that this call is to a non-template function
server::display_integers(input);
std::list<int> input2;
input2 += 6,7,8,9,10;
// Note that this call is to the same non-tempate function
server::display_integers(input2);
input2.clear();
input2 += 11,12,13,14,15;
// Calling using the adaptor looks like this:
// Notice that here I have a type_erased that would be a
// bidirectional_traversal_tag, but this is convertible
// to the forward_traversal_tag equivalent hence this
// works.
server::display_integers(input2 | type_erased<>());
// However we may simply wish to define an adaptor that
// takes a range and makes it into an appropriate
// forward_traversal any_range...
typedef boost::adaptors::type_erased<
boost::use_default
, boost::forward_traversal_tag
> type_erased_forward;
// This adaptor can turn other containers with different
// value_types and reference_types into the appropriate
// any_range.
server::display_integers(input2 | type_erased_forward());
}
}
} // namespace type_erased_example
} // namespace boost_range_test
} // anonymous namespace
boost::unit_test::test_suite*
init_unit_test_suite(int argc, char* argv[])
{
boost::unit_test::test_suite* test
= BOOST_TEST_SUITE( "RangeTestSuite.adaptor.type_erased_example" );
test->add( BOOST_TEST_CASE( &boost_range_test::type_erased_example::client::run) );
return test;
}
+119
View File
@@ -0,0 +1,119 @@
// Boost.Range library
//
// Copyright Neil Groves 2010. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see http://www.boost.org/libs/range/
//
#include <boost/detail/workaround.hpp>
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
# pragma warn -8091 // supress warning in Boost.Test
# pragma warn -8057 // unused argument argc/argv in Boost.Test
#endif
#include <boost/range/begin.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/test/included/unit_test_framework.hpp>
namespace mock_std
{
template<class SinglePassRange>
inline BOOST_DEDUCED_TYPENAME boost::range_iterator<SinglePassRange>::type
begin(SinglePassRange& rng)
{
return rng.begin();
}
template<class SinglePassRange>
inline BOOST_DEDUCED_TYPENAME boost::range_iterator<const SinglePassRange>::type
begin(const SinglePassRange& rng)
{
return rng.begin();
}
template<class SinglePassRange>
void mock_algorithm_using_begin(const SinglePassRange& rng)
{
BOOST_CHECK( begin(rng) == rng.begin() );
}
template<class SinglePassRange>
void mock_algorithm_using_begin(SinglePassRange& rng)
{
BOOST_CHECK( begin(rng) == rng.begin() );
}
}
namespace boost
{
#ifdef BOOST_RANGE_SIMULATE_BEGIN_WITHOUT_ADL_NAMESPACE_BARRIER
template<class SinglePassRange>
inline BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type
begin(SinglePassRange& rng)
{
return rng.begin();
}
template<class SinglePassRange>
inline BOOST_DEDUCED_TYPENAME range_iterator<const SinglePassRange>::type
begin(const SinglePassRange& rng)
{
return rng.begin();
}
#endif
class MockTestBeginCollection
{
public:
typedef char value_type;
typedef const char* const_pointer;
typedef char* pointer;
typedef const_pointer const_iterator;
typedef pointer iterator;
MockTestBeginCollection()
: m_first()
, m_last()
{
}
const_iterator begin() const { return m_first; }
iterator begin() { return m_first; }
const_iterator end() const { return m_last; }
iterator end() { return m_last; }
private:
iterator m_first;
iterator m_last;
};
}
namespace
{
void test_range_begin()
{
boost::MockTestBeginCollection c;
const boost::MockTestBeginCollection& const_c = c;
mock_std::mock_algorithm_using_begin(const_c);
mock_std::mock_algorithm_using_begin(c);
}
}
using boost::unit_test_framework::test_suite;
boost::unit_test_framework::test_suite*
init_unit_test_suite( int argc, char* argv[] )
{
boost::unit_test_framework::test_suite* test = BOOST_TEST_SUITE( "Range Test Suite - begin() ADL namespace barrier" );
test->add( BOOST_TEST_CASE( &test_range_begin ) );
return test;
}
+119
View File
@@ -0,0 +1,119 @@
// Boost.Range library
//
// Copyright Neil Groves 2010. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see http://www.boost.org/libs/range/
//
#include <boost/detail/workaround.hpp>
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
# pragma warn -8091 // supress warning in Boost.Test
# pragma warn -8057 // unused argument argc/argv in Boost.Test
#endif
#include <boost/range/end.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/test_tools.hpp>
#include <boost/test/included/unit_test_framework.hpp>
namespace mock_std
{
template<class SinglePassRange>
inline BOOST_DEDUCED_TYPENAME boost::range_iterator<SinglePassRange>::type
end(SinglePassRange& rng)
{
return rng.end();
}
template<class SinglePassRange>
inline BOOST_DEDUCED_TYPENAME boost::range_iterator<const SinglePassRange>::type
end(const SinglePassRange& rng)
{
return rng.end();
}
template<class SinglePassRange>
void mock_algorithm_using_end(const SinglePassRange& rng)
{
BOOST_CHECK( end(rng) == rng.end() );
}
template<class SinglePassRange>
void mock_algorithm_using_end(SinglePassRange& rng)
{
BOOST_CHECK( end(rng) == rng.end() );
}
}
namespace boost
{
#ifdef BOOST_RANGE_SIMULATE_END_WITHOUT_ADL_NAMESPACE_BARRIER
template<class SinglePassRange>
inline BOOST_DEDUCED_TYPENAME range_iterator<SinglePassRange>::type
end(SinglePassRange& rng)
{
return rng.end();
}
template<class SinglePassRange>
inline BOOST_DEDUCED_TYPENAME range_iterator<const SinglePassRange>::type
end(const SinglePassRange& rng)
{
return rng.end();
}
#endif
class MockTestEndCollection
{
public:
typedef char value_type;
typedef const char* const_pointer;
typedef char* pointer;
typedef const_pointer const_iterator;
typedef pointer iterator;
MockTestEndCollection()
: m_first()
, m_last()
{
}
const_iterator begin() const { return m_first; }
iterator begin() { return m_first; }
const_iterator end() const { return m_last; }
iterator end() { return m_last; }
private:
iterator m_first;
iterator m_last;
};
}
namespace
{
void test_range_end_adl_avoidance()
{
boost::MockTestEndCollection c;
const boost::MockTestEndCollection& const_c = c;
mock_std::mock_algorithm_using_end(const_c);
mock_std::mock_algorithm_using_end(c);
}
}
using boost::unit_test_framework::test_suite;
boost::unit_test_framework::test_suite*
init_unit_test_suite( int argc, char* argv[] )
{
boost::unit_test_framework::test_suite* test = BOOST_TEST_SUITE( "Range Test Suite - end() ADL namespace barrier" );
test->add( BOOST_TEST_CASE( &test_range_end_adl_avoidance ) );
return test;
}