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 #include <boost/detail/workaround.hpp>
12
13 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
14 # pragma warn -8091 // suppress warning in Boost.Test
15 # pragma warn -8057 // unused argument argc/argv in Boost.Test
16 #endif
17
18 #include <boost/test/unit_test.hpp>
19 #include <boost/test/test_tools.hpp>
20
21 enum adl_types
22 {
23 unused,
24 boost_namespace,
25 templated_namespace,
26 non_templated_namespace,
27 global_namespace
28 };
29
30 // Use boost_test rather than boost as the namespace for this test
31 // to allow the test framework to use boost::begin() etc. without
32 // violating the One Defintion Rule.
33 namespace boost_test
34 {
35 namespace range_detail
36 {
37 template< class Range >
begin(Range & r)38 inline typename Range::iterator begin( Range& r )
39 {
40 return boost_namespace;
41 }
42
43 template< class Range >
begin(const Range & r)44 inline typename Range::iterator begin( const Range& r )
45 {
46 return boost_namespace;
47 }
48
49 }
50
51 template< class Range >
begin(Range & r)52 inline typename Range::iterator begin( Range& r )
53 {
54 using range_detail::begin; // create ADL hook
55 return begin( r );
56 }
57
58 template< class Range >
begin(const Range & r)59 inline typename Range::iterator begin( const Range& r )
60 {
61 using range_detail::begin; // create ADL hook
62 return begin( r );
63 }
64 } // 'boost_test'
65
66
67 namespace find_templated
68 {
69 template< class T >
70 struct range
71 {
72 typedef adl_types iterator;
73
rangefind_templated::range74 range() { /* allow const objects */ }
beginfind_templated::range75 iterator begin() { return unused; }
beginfind_templated::range76 iterator begin() const { return unused; }
endfind_templated::range77 iterator end() { return unused; }
endfind_templated::range78 iterator end() const { return unused; }
79 };
80
81 //
82 // A fully generic version here will create
83 // ambiguity.
84 //
85 template< class T >
begin(range<T> & r)86 inline typename range<T>::iterator begin( range<T>& r )
87 {
88 return templated_namespace;
89 }
90
91 template< class T >
begin(const range<T> & r)92 inline typename range<T>::iterator begin( const range<T>& r )
93 {
94 return templated_namespace;
95 }
96
97 }
98
99 namespace find_non_templated
100 {
101 struct range
102 {
103 typedef adl_types iterator;
104
rangefind_non_templated::range105 range() { /* allow const objects */ }
beginfind_non_templated::range106 iterator begin() { return unused; }
beginfind_non_templated::range107 iterator begin() const { return unused; }
endfind_non_templated::range108 iterator end() { return unused; }
endfind_non_templated::range109 iterator end() const { return unused; }
110 };
111
begin(range & r)112 inline range::iterator begin( range& r )
113 {
114 return non_templated_namespace;
115 }
116
117
begin(const range & r)118 inline range::iterator begin( const range& r )
119 {
120 return non_templated_namespace;
121 }
122 }
123
124 struct range
125 {
126 typedef adl_types iterator;
127
rangerange128 range() { /* allow const objects */ }
beginrange129 iterator begin() { return unused; }
beginrange130 iterator begin() const { return unused; }
endrange131 iterator end() { return unused; }
endrange132 iterator end() const { return unused; }
133 };
134
begin(range & r)135 inline range::iterator begin( range& r )
136 {
137 return global_namespace;
138 }
139
begin(const range & r)140 inline range::iterator begin( const range& r )
141 {
142 return global_namespace;
143 }
144
check_adl_conformance()145 void check_adl_conformance()
146 {
147 find_templated::range<int> r;
148 const find_templated::range<int> r2;
149 find_non_templated::range r3;
150 const find_non_templated::range r4;
151 range r5;
152 const range r6;
153
154 //
155 // Notice how ADL kicks in even when we have qualified
156 // notation!
157 //
158
159
160 BOOST_CHECK( boost_test::begin( r ) != boost_namespace );
161 BOOST_CHECK( boost_test::begin( r2 ) != boost_namespace );
162 BOOST_CHECK( boost_test::begin( r3 ) != boost_namespace );
163 BOOST_CHECK( boost_test::begin( r4 ) != boost_namespace );
164 BOOST_CHECK( boost_test::begin( r5 ) != boost_namespace );
165 BOOST_CHECK( boost_test::begin( r6 ) != boost_namespace );
166
167 BOOST_CHECK_EQUAL( boost_test::begin( r ), templated_namespace ) ;
168 BOOST_CHECK_EQUAL( boost_test::begin( r2 ), templated_namespace );
169 BOOST_CHECK_EQUAL( boost_test::begin( r3 ), non_templated_namespace );
170 BOOST_CHECK_EQUAL( boost_test::begin( r4 ), non_templated_namespace );
171 BOOST_CHECK_EQUAL( boost_test::begin( r5 ), global_namespace );
172 BOOST_CHECK_EQUAL( boost_test::begin( r6 ), global_namespace );
173 }
174
175 #include <boost/test/included/unit_test.hpp>
176
177 using boost::unit_test::test_suite;
178
init_unit_test_suite(int argc,char * argv[])179 test_suite* init_unit_test_suite( int argc, char* argv[] )
180 {
181 test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" );
182
183 test->add( BOOST_TEST_CASE( &check_adl_conformance ) );
184
185 return test;
186 }
187
188
189