1 // Boost.Range library
2 //
3 //  Copyright Thorsten Ottosen 2003-2004. Use, modification and
4 //  distribution is subject to the Boost Software License, Version
5 //  1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 //  http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // For more information, see http://www.boost.org/libs/range/
9 //
10 
11 
12 #include <boost/detail/workaround.hpp>
13 
14 #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564))
15 #  pragma warn -8091 // suppress warning in Boost.Test
16 #  pragma warn -8057 // unused argument argc/argv in Boost.Test
17 #endif
18 
19 #include <boost/range.hpp>
20 #include <boost/test/test_tools.hpp>
21 #include <boost/test/unit_test.hpp>
22 #include <boost/static_assert.hpp>
23 #include <boost/cstdint.hpp>
24 #include <list>
25 #include <vector>
26 
27 namespace boost_range_extension_size_test
28 {
29     class FooWithoutSize
30     {
31         typedef std::list<int> impl_t;
32 
33         BOOST_STATIC_ASSERT((
34             boost::is_same<
35                 boost::range_size<std::list<int> >::type,
36                 std::list<int>::size_type
37             >::value));
38 
39         typedef impl_t::const_iterator const_iterator;
40         typedef impl_t::iterator iterator;
41 
42     public:
range_begin(const FooWithoutSize & obj)43         friend inline const_iterator range_begin(const FooWithoutSize& obj) { return obj.m_impl.begin(); }
range_begin(FooWithoutSize & obj)44         friend inline iterator range_begin(FooWithoutSize& obj) { return obj.m_impl.begin(); }
range_end(const FooWithoutSize & obj)45         friend inline const_iterator range_end(const FooWithoutSize& obj) { return obj.m_impl.end(); }
range_end(FooWithoutSize & obj)46         friend inline iterator range_end(FooWithoutSize& obj){ return obj.m_impl.end(); }
47 
48     private:
49         impl_t m_impl;
50     };
51 
52     template<typename SizeType>
53     class FooWithSize
54     {
55     public:
56         typedef SizeType size_type;
57         typedef boost::uint8_t* iterator;
58         typedef const boost::uint8_t* const_iterator;
59 
60         const_iterator begin() const;
61         iterator begin();
62         const_iterator end() const;
63         iterator end();
64     };
65 
66     BOOST_STATIC_ASSERT((
67         boost::is_same<
68             boost::uint8_t,
69             boost::range_size<FooWithSize<boost::uint8_t> >::type
70         >::value
71     ));
72 
73     BOOST_STATIC_ASSERT((
74         boost::is_same<
75             boost::uint16_t,
76             boost::range_size<FooWithSize<boost::uint16_t> >::type
77         >::value
78     ));
79 
80     BOOST_STATIC_ASSERT((
81         boost::is_same<
82             boost::uint32_t,
83             boost::range_size<FooWithSize<boost::uint32_t> >::type
84         >::value
85     ));
86 
87     BOOST_STATIC_ASSERT((
88         boost::is_same<
89             boost::uint64_t,
90             boost::range_size<FooWithSize<boost::uint64_t> >::type
91         >::value
92     ));
93 
94     class UdtSizeType
95     {
96     public:
97         typedef boost::uint16_t value_type;
98 
UdtSizeType()99         UdtSizeType() : value_(0) { }
UdtSizeType(value_type value)100         UdtSizeType(value_type value) : value_(value) { }
101 
operator value_type() const102         operator value_type() const { return value_; }
103 
104     private:
105         value_type value_;
106     };
107 
108     BOOST_STATIC_ASSERT((
109         boost::is_same<
110             UdtSizeType,
111             boost::range_size<FooWithSize<UdtSizeType> >::type
112         >::value
113     ));
114 
115     class Foo2WithoutSize
116     {
117     public:
118         struct const_iterator
119         {
120             typedef std::forward_iterator_tag iterator_category;
121             typedef boost::int8_t difference_type;
122             typedef boost::int16_t value_type;
123             typedef value_type* pointer;
124             typedef value_type& reference;
125 
126             reference operator*() const;
127             pointer operator->() const;
128             const_iterator& operator++();
129             const_iterator operator++(int);
130             bool operator==(const const_iterator&) const;
131             bool operator!=(const const_iterator&) const;
132         };
133 
134         struct iterator : const_iterator
135         {
136             typedef const value_type* pointer;
137             typedef const value_type& reference;
138 
139             reference operator*() const;
140             pointer operator->() const;
141 
142             iterator& operator++();
143             iterator operator++(int);
144 
145             bool operator==(const iterator&) const;
146             bool operator!=(const iterator&) const;
147         };
148 
149         const_iterator begin() const;
150         iterator begin();
151         const_iterator end() const;
152         iterator end();
153     };
154 
155     BOOST_STATIC_ASSERT((
156         boost::is_same<
157             boost::uint8_t,
158             boost::range_size<
159                 ::boost_range_extension_size_test::Foo2WithoutSize>::type
160         >::value
161     ));
162 }
163 
164 namespace boost
165 {
166     template<> struct range_iterator<const ::boost_range_extension_size_test::FooWithoutSize>
167     {
168         typedef std::list<int>::const_iterator type;
169     };
170 
171     template<> struct range_iterator< ::boost_range_extension_size_test::FooWithoutSize>
172     {
173         typedef std::list<int>::iterator type;
174     };
175 }
176 
177 namespace boost_range_extension_size_test
178 {
179     inline boost::range_size<FooWithoutSize>::type
range_calculate_size(const FooWithoutSize & rng)180     range_calculate_size(const FooWithoutSize& rng)
181     {
182         return 2u;
183     }
184 }
185 
186 BOOST_STATIC_ASSERT((
187     boost::is_same<
188         boost::make_unsigned<std::ptrdiff_t>::type,
189         boost::range_size<
190                     boost_range_extension_size_test::FooWithoutSize>::type
191     >::value
192 ));
193 
194 typedef boost::make_unsigned<std::ptrdiff_t>::type t1;
195 typedef boost::range_size<boost_range_extension_size_test::FooWithoutSize>::type t1;
196 
197 namespace
198 {
199 
check_size_works_with_random_access()200 void check_size_works_with_random_access()
201 {
202     std::vector<int> container;
203     container.push_back(1);
204     BOOST_CHECK_EQUAL( boost::size(container), 1u );
205 }
206 
check_extension_size()207 void check_extension_size()
208 {
209     BOOST_CHECK_EQUAL( boost::size(boost_range_extension_size_test::FooWithoutSize()), 2u );
210 }
211 
212 } // anonymous namespace
213 
214 using boost::unit_test::test_suite;
215 
init_unit_test_suite(int argc,char * argv[])216 test_suite* init_unit_test_suite( int argc, char* argv[] )
217 {
218     test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" );
219 
220     test->add( BOOST_TEST_CASE( &check_size_works_with_random_access ));
221     test->add( BOOST_TEST_CASE( &check_extension_size ) );
222 
223     return test;
224 }
225