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