1 //  Copyright Neil Groves 2009. Use, modification and
2 //  distribution is subject to the Boost Software License, Version
3 //  1.0. (See accompanying file LICENSE_1_0.txt or copy at
4 //  http://www.boost.org/LICENSE_1_0.txt)
5 //
6 //
7 // For more information, see http://www.boost.org/libs/range/
8 //
9 #include <boost/range/algorithm/lower_bound.hpp>
10 
11 #include <boost/test/test_tools.hpp>
12 #include <boost/test/unit_test.hpp>
13 
14 #include <boost/assign.hpp>
15 #include <boost/range/algorithm/lower_bound.hpp>
16 #include "../test_driver/range_return_test_driver.hpp"
17 #include <algorithm>
18 #include <functional>
19 #include <list>
20 #include <numeric>
21 #include <deque>
22 #include <vector>
23 
24 namespace boost_range_test_algorithm_lower_bound
25 {
26     class lower_bound_policy
27     {
28     public:
29         template< class Container >
30         BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type
test_iter(Container & cont)31         test_iter(Container& cont)
32         {
33             typedef BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type iter_t;
34             iter_t result = boost::lower_bound(cont, 5);
35             BOOST_CHECK( result == boost::lower_bound(boost::make_iterator_range(cont), 5) );
36             return result;
37         }
38 
39         template<boost::range_return_value return_type>
40         struct test_range
41         {
42             template<class Container, class Policy>
43             BOOST_DEDUCED_TYPENAME boost::range_return<Container,return_type>::type
operator ()boost_range_test_algorithm_lower_bound::lower_bound_policy::test_range44             operator()(Policy&, Container& cont)
45             {
46                 typedef BOOST_DEDUCED_TYPENAME boost::range_return<Container,return_type>::type result_t;
47                 result_t result = boost::lower_bound<return_type>(cont, 5);
48                 BOOST_CHECK( result == boost::lower_bound<return_type>(boost::make_iterator_range(cont), 5) );
49                 return result;
50             }
51         };
52 
53         template< class Container >
54         BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type
reference(Container & cont)55         reference(Container& cont)
56         {
57             return std::lower_bound(cont.begin(), cont.end(), 5);
58         }
59     };
60 
61     template< class BinaryPredicate >
62     struct lower_bound_pred_policy
63     {
64         template< class Container >
65         BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type
test_iterboost_range_test_algorithm_lower_bound::lower_bound_pred_policy66         test_iter(Container& cont)
67         {
68             typedef BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type iter_t;
69             iter_t result = boost::lower_bound(cont, 5, m_pred);
70             BOOST_CHECK( result == boost::lower_bound(
71                                     boost::make_iterator_range(cont), 5, m_pred) );
72             return result;
73         }
74 
75         template< boost::range_return_value return_type >
76         struct test_range
77         {
78             template<class Container, class Policy>
79             BOOST_DEDUCED_TYPENAME boost::range_return<Container,return_type>::type
operator ()boost_range_test_algorithm_lower_bound::lower_bound_pred_policy::test_range80             operator()(Policy& policy, Container& cont)
81             {
82                 typedef BOOST_DEDUCED_TYPENAME boost::range_return<Container,return_type>::type result_t;
83                 result_t result = boost::lower_bound<return_type>(cont, 5, policy.pred());
84                 BOOST_CHECK( result == boost::lower_bound<return_type>(
85                                         boost::make_iterator_range(cont), 5, policy.pred()) );
86                 return result;
87             }
88         };
89 
90         template<class Container>
91         BOOST_DEDUCED_TYPENAME boost::range_iterator<Container>::type
referenceboost_range_test_algorithm_lower_bound::lower_bound_pred_policy92         reference(Container& cont)
93         {
94             return std::lower_bound(
95                     cont.begin(), cont.end(), 5, m_pred);
96         }
97 
predboost_range_test_algorithm_lower_bound::lower_bound_pred_policy98         BinaryPredicate& pred() { return m_pred; }
99 
100     private:
101         BinaryPredicate m_pred;
102     };
103 
104     template<class Container,
105              class TestPolicy,
106              class BinaryPredicate>
test_lower_bound_impl(TestPolicy policy,BinaryPredicate pred)107     void test_lower_bound_impl(TestPolicy policy, BinaryPredicate pred)
108     {
109         using namespace boost::assign;
110 
111         typedef BOOST_DEDUCED_TYPENAME boost::remove_const<Container>::type container_t;
112         typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t;
113 
114         boost::range_test::range_return_test_driver test_driver;
115 
116         container_t mcont;
117         Container& cont = mcont;
118 
119         test_driver(cont, policy);
120 
121         mcont.clear();
122         mcont += 1;
123 
124         std::vector<value_t> temp(mcont.begin(), mcont.end());
125         std::sort(temp.begin(), temp.end(), pred);
126         mcont.assign(temp.begin(), temp.end());
127 
128         test_driver(cont, policy);
129 
130         mcont.clear();
131         mcont += 1,2,3,4,5,6,7,8,9;
132 
133         temp.assign(mcont.begin(), mcont.end());
134         std::sort(temp.begin(), temp.end(), pred);
135         mcont.assign(temp.begin(), temp.end());
136 
137         test_driver(cont, policy);
138     }
139 
140     template<class Container>
test_lower_bound_impl()141     void test_lower_bound_impl()
142     {
143         test_lower_bound_impl<Container>(
144             lower_bound_policy(),
145             std::less<int>()
146             );
147 
148         test_lower_bound_impl<Container>(
149             lower_bound_pred_policy<std::less<int> >(),
150             std::less<int>()
151             );
152 
153         test_lower_bound_impl<Container>(
154             lower_bound_pred_policy<std::greater<int> >(),
155             std::greater<int>()
156             );
157     }
158 
test_lower_bound()159     void test_lower_bound()
160     {
161         test_lower_bound_impl< std::vector<int> >();
162         test_lower_bound_impl< std::list<int> >();
163         test_lower_bound_impl< std::deque<int> >();
164 
165         test_lower_bound_impl< const std::vector<int> >();
166         test_lower_bound_impl< const std::list<int> >();
167         test_lower_bound_impl< const std::deque<int> >();
168     }
169 }
170 
171 boost::unit_test::test_suite*
init_unit_test_suite(int argc,char * argv[])172 init_unit_test_suite(int argc, char* argv[])
173 {
174     boost::unit_test::test_suite* test
175         = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.lower_bound" );
176 
177     test->add( BOOST_TEST_CASE( &boost_range_test_algorithm_lower_bound::test_lower_bound ) );
178 
179     return test;
180 }
181