Imported Upstream version 1.57.0
[platform/upstream/boost.git] / libs / range / test / adaptor_test / indexed.cpp
index 2a9c45d..f4085be 100644 (file)
@@ -1,6 +1,6 @@
 // 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;
 }