// Boost.Range library
//
-// Copyright Neil Groves 2009. Use, modification and
+// Copyright Neil Groves 2014. 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/test/unit_test.hpp>
#include <boost/assign.hpp>
+#include <boost/foreach.hpp>
#include <boost/range/algorithm_ext.hpp>
+#include <boost/range/concepts.hpp>
#include <algorithm>
#include <list>
#include <vector>
-namespace boost
+#include "../test_utils.hpp"
+
+namespace boost_range_test
{
namespace
{
- template< class Container >
- void indexed_test_impl( Container& c )
- {
- using namespace boost::adaptors;
- typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t;
+template<typename Container, typename AdaptedRange>
+void check_result(
+ const Container& reference_range,
+ const AdaptedRange& adapted_range,
+ std::ptrdiff_t start_index
+ )
+{
+ typedef typename boost::range_iterator<const Container>::type
+ reference_iterator;
+
+ typedef typename boost::range_iterator<const AdaptedRange>::type
+ adapted_iterator;
+
+ BOOST_REQUIRE_EQUAL(boost::size(reference_range),
+ boost::size(adapted_range));
+
+ reference_iterator reference_it = boost::begin(reference_range);
+ adapted_iterator adapted_it = boost::begin(adapted_range);
+ for (std::ptrdiff_t i = start_index;
+ reference_it != boost::end(reference_range);
+ ++reference_it, ++adapted_it, ++i)
+ {
+ BOOST_CHECK_EQUAL(i, adapted_it->index());
+ BOOST_CHECK_EQUAL(*reference_it, adapted_it->value());
+ }
+}
+
+template<typename Container>
+void indexed_test_impl(Container& c, std::ptrdiff_t start_index)
+{
+ // This is my preferred syntax using the | operator.
+ check_result(c, c | boost::adaptors::indexed(), 0);
+ check_result(c, c | boost::adaptors::indexed(start_index), start_index);
+
+ // This is the function syntax
+ check_result(c, boost::adaptors::index(c), 0);
+ check_result(c, boost::adaptors::index(c, start_index), start_index);
+}
+
+template<typename Container>
+void indexed_test_impl(Container& c)
+{
+ indexed_test_impl(c, 0);
+ indexed_test_impl(c, -1);
+ indexed_test_impl(c, 4);
+}
- // This is my preferred syntax using the | operator.
- std::vector< value_t > test_result1;
- boost::push_back(test_result1, c | indexed(0));
+template<typename Container>
+void indexed_test_impl()
+{
+ using namespace boost::assign;
- // This is an alternative syntax preferred by some.
- std::vector< value_t > test_result2;
- boost::push_back(test_result2, adaptors::index(c, 0));
+ Container c;
- BOOST_CHECK_EQUAL_COLLECTIONS( c.begin(), c.end(),
- test_result1.begin(), test_result1.end() );
+ // test empty container
+ indexed_test_impl(c);
- BOOST_CHECK_EQUAL_COLLECTIONS( c.begin(), c.end(),
- test_result2.begin(), test_result2.end() );
+ // test one element
+ c += 1;
+ indexed_test_impl(c);
- boost::indexed_range< Container > test_result3
- = c | indexed(0);
+ // test many elements
+ c += 1,2,2,2,3,4,4,4,4,5,6,7,8,9,9;
+ indexed_test_impl(c);
+}
- typedef BOOST_DEDUCED_TYPENAME boost::range_const_iterator<
- boost::indexed_range< Container > >::type iter_t;
+template<typename Traversal, typename Range>
+void check_traversal(const Range& rng)
+{
+ BOOST_STATIC_ASSERT(
+ boost::is_convertible<
+ typename boost::range_traversal<const Range>::type,
+ Traversal
+ >::value);
+}
- iter_t it = test_result3.begin();
- for (std::size_t i = 0, count = c.size(); i < count; ++i)
- {
- BOOST_CHECK_EQUAL( i, static_cast<std::size_t>(it.index()) );
- ++it;
- }
+template<typename Traversal, typename Range>
+void check_not_traversal(const Range& rng)
+{
+ BOOST_STATIC_ASSERT(
+ !boost::is_convertible<
+ typename boost::range_traversal<const Range>::type,
+ Traversal
+ >::value);
+}
- }
+void indexed_test()
+{
+ indexed_test_impl< std::vector< int > >();
+ indexed_test_impl< std::list< int > >();
- template< class Container >
- void indexed_test_impl()
- {
- using namespace boost::assign;
+ std::vector<int> vi;
- Container c;
+ check_traversal<boost::random_access_traversal_tag>(
+ vi | boost::adaptors::indexed());
- // test empty container
- indexed_test_impl(c);
+ std::list<int> li;
- // test one element
- c += 1;
- indexed_test_impl(c);
+ check_traversal<boost::forward_traversal_tag>(
+ li | boost::adaptors::indexed());
- // test many elements
- c += 1,2,2,2,3,4,4,4,4,5,6,7,8,9,9;
- indexed_test_impl(c);
- }
+ check_not_traversal<boost::bidirectional_traversal_tag>(
+ li | boost::adaptors::indexed());
- void indexed_test()
- {
- indexed_test_impl< std::vector< int > >();
- indexed_test_impl< std::list< int > >();
- }
- }
+ check_not_traversal<boost::random_access_traversal_tag>(
+ li | boost::adaptors::indexed());
}
+ } // anonymous namesapce
+} // namespace boost_range_test
+
boost::unit_test::test_suite*
-init_unit_test_suite(int argc, char* argv[])
+init_unit_test_suite(int, char*[])
{
boost::unit_test::test_suite* test
- = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.indexed" );
+ = BOOST_TEST_SUITE( "Boost.Range indexed adaptor test suite" );
- test->add( BOOST_TEST_CASE( &boost::indexed_test ) );
+ test->add(BOOST_TEST_CASE(&boost_range_test::indexed_test));
return test;
}