1// (C) Copyright Eric Niebler 2004-2005
2// (C) Copyright Gennadiy Rozental 2001.
3// Distributed under the Boost Software License, Version 1.0.
4// (See accompanying file LICENSE_1_0.txt or copy at
5// http://www.boost.org/LICENSE_1_0.txt)
6
7// See http://www.boost.org/libs/test for the library home page.
8//
9// File : $RCSfile$
10//
11// Version : $Revision$
12//
13// Description : this is an abridged version of an excelent BOOST_FOREACH facility
14// presented by Eric Niebler. I am so fond of it so I can't wait till it
15// going to be accepted into Boost. Also I need version with less number of dependencies
16// and more portable. This version doesn't support rvalues and will reeveluate it's
17// parameters, but should be good enough for my purposes.
18// ***************************************************************************
19
20#ifndef BOOST_TEST_UTILS_FOREACH_HPP
21#define BOOST_TEST_UTILS_FOREACH_HPP
22
23// Boost.Test
24#include <boost/test/detail/config.hpp>
25
26// Boost
27#include <boost/type.hpp>
28#include <boost/mpl/bool.hpp>
29#include <boost/test/detail/workaround.hpp>
30
31#include <boost/type_traits/is_const.hpp>
32
33#include <boost/test/detail/suppress_warnings.hpp>
34
35//____________________________________________________________________________//
36
37namespace boost {
38namespace unit_test {
39namespace for_each {
40
41// ************************************************************************** //
42// ************** static_any ************** //
43// ************************************************************************** //
44
45struct static_any_base
46{
47 operator bool() const { return false; }
48};
49
50//____________________________________________________________________________//
51
52template<typename Iter>
53struct static_any : static_any_base
54{
55 static_any( Iter const& t ) : m_it( t ) {}
56
57 mutable Iter m_it;
58};
59
60//____________________________________________________________________________//
61
62typedef static_any_base const& static_any_t;
63
64//____________________________________________________________________________//
65
66template<typename Iter>
67inline Iter&
68static_any_cast( static_any_t a, Iter* = 0 )
69{
70 return static_cast<Iter&>( static_cast<static_any<Iter> const&>( a ).m_it );
71}
72
73//____________________________________________________________________________//
74
75// ************************************************************************** //
76// ************** is_const ************** //
77// ************************************************************************** //
78
79template<typename C>
80inline is_const<C>
81is_const_coll( C& )
82{
83 return is_const<C>();
84}
85
86//____________________________________________________________________________//
87
88// ************************************************************************** //
89// ************** begin ************** //
90// ************************************************************************** //
91
92template<typename C>
93inline static_any<BOOST_DEDUCED_TYPENAME C::iterator>
94begin( C& t, mpl::false_ )
95{
96 return static_any<BOOST_DEDUCED_TYPENAME C::iterator>( t.begin() );
97}
98
99//____________________________________________________________________________//
100
101template<typename C>
102inline static_any<BOOST_DEDUCED_TYPENAME C::const_iterator>
103begin( C const& t, mpl::true_ )
104{
105 return static_any<BOOST_DEDUCED_TYPENAME C::const_iterator>( t.begin() );
106}
107
108//____________________________________________________________________________//
109
110// ************************************************************************** //
111// ************** end ************** //
112// ************************************************************************** //
113
114template<typename C>
115inline static_any<BOOST_DEDUCED_TYPENAME C::iterator>
116end( C& t, mpl::false_ )
117{
118 return static_any<BOOST_DEDUCED_TYPENAME C::iterator>( t.end() );
119}
120
121//____________________________________________________________________________//
122
123template<typename C>
124inline static_any<BOOST_DEDUCED_TYPENAME C::const_iterator>
125end( C const& t, mpl::true_ )
126{
127 return static_any<BOOST_DEDUCED_TYPENAME C::const_iterator>( t.end() );
128}
129
130//____________________________________________________________________________//
131
132// ************************************************************************** //
133// ************** done ************** //
134// ************************************************************************** //
135
136template<typename C>
137inline bool
138done( static_any_t cur, static_any_t end, C&, mpl::false_ )
139{
140 return static_any_cast<BOOST_DEDUCED_TYPENAME C::iterator>( cur ) ==
141 static_any_cast<BOOST_DEDUCED_TYPENAME C::iterator>( end );
142}
143
144//____________________________________________________________________________//
145
146template<typename C>
147inline bool
148done( static_any_t cur, static_any_t end, C const&, mpl::true_ )
149{
150 return static_any_cast<BOOST_DEDUCED_TYPENAME C::const_iterator>( cur ) ==
151 static_any_cast<BOOST_DEDUCED_TYPENAME C::const_iterator>( end );
152}
153
154//____________________________________________________________________________//
155
156// ************************************************************************** //
157// ************** next ************** //
158// ************************************************************************** //
159
160template<typename C>
161inline void
162next( static_any_t cur, C&, mpl::false_ )
163{
164 ++static_any_cast<BOOST_DEDUCED_TYPENAME C::iterator>( cur );
165}
166
167//____________________________________________________________________________//
168
169template<typename C>
170inline void
171next( static_any_t cur, C const&, mpl::true_ )
172{
173 ++static_any_cast<BOOST_DEDUCED_TYPENAME C::const_iterator>( cur );
174}
175
176//____________________________________________________________________________//
177
178// ************************************************************************** //
179// ************** prev ************** //
180// ************************************************************************** //
181
182template<typename C>
183inline void
184prev( static_any_t cur, C&, mpl::false_ )
185{
186 --static_any_cast<BOOST_DEDUCED_TYPENAME C::iterator>( cur );
187}
188
189//____________________________________________________________________________//
190
191template<typename C>
192inline void
193prev( static_any_t cur, C const&, mpl::true_ )
194{
195 --static_any_cast<BOOST_DEDUCED_TYPENAME C::const_iterator>( cur );
196}
197
198//____________________________________________________________________________//
199
200// ************************************************************************** //
201// ************** deref ************** //
202// ************************************************************************** //
203
204template<class RefType,typename C>
205inline RefType
206deref( static_any_t cur, C&, ::boost::type<RefType>, mpl::false_ )
207{
208 return *static_any_cast<BOOST_DEDUCED_TYPENAME C::iterator>( cur );
209}
210
211//____________________________________________________________________________//
212
213template<class RefType,typename C>
214inline RefType
215deref( static_any_t cur, C const&, ::boost::type<RefType>, mpl::true_ )
216{
217 return *static_any_cast<BOOST_DEDUCED_TYPENAME C::const_iterator>( cur );
218}
219
220//____________________________________________________________________________//
221
222// ************************************************************************** //
223// ************** BOOST_TEST_FOREACH ************** //
224// ************************************************************************** //
225
226#define BOOST_TEST_FE_ANY ::boost::unit_test::for_each::static_any_t
227#define BOOST_TEST_FE_IS_CONST( COL ) ::boost::unit_test::for_each::is_const_coll( COL )
228
229#define BOOST_TEST_FE_BEG( COL ) \
230 ::boost::unit_test::for_each::begin( \
231 COL, \
232 BOOST_TEST_FE_IS_CONST( COL ) ) \
233/**/
234
235#define BOOST_TEST_FE_END( COL ) \
236 ::boost::unit_test::for_each::end( \
237 COL, \
238 BOOST_TEST_FE_IS_CONST( COL ) ) \
239/**/
240
241#define BOOST_TEST_FE_DONE( COL ) \
242 ::boost::unit_test::for_each::done( \
243 BOOST_TEST_FE_CUR_VAR, \
244 BOOST_TEST_FE_END_VAR, \
245 COL, \
246 BOOST_TEST_FE_IS_CONST( COL ) ) \
247/**/
248
249#define BOOST_TEST_FE_NEXT( COL ) \
250 ::boost::unit_test::for_each::next( \
251 BOOST_TEST_FE_CUR_VAR, \
252 COL, \
253 BOOST_TEST_FE_IS_CONST( COL ) ) \
254/**/
255
256#define BOOST_TEST_FE_PREV( COL ) \
257 ::boost::unit_test::for_each::prev( \
258 BOOST_TEST_FE_CUR_VAR, \
259 COL, \
260 BOOST_TEST_FE_IS_CONST( COL ) ) \
261/**/
262
263#define BOOST_FOREACH_NOOP(COL) \
264 ((void)&(COL))
265
266#define BOOST_TEST_FE_DEREF( COL, RefType ) \
267 ::boost::unit_test::for_each::deref( \
268 BOOST_TEST_FE_CUR_VAR, \
269 COL, \
270 ::boost::type<RefType >(), \
271 BOOST_TEST_FE_IS_CONST( COL ) ) \
272/**/
273
274#if BOOST_WORKAROUND( BOOST_MSVC, == 1310 )
275#define BOOST_TEST_LINE_NUM
276#else
277#define BOOST_TEST_LINE_NUM __LINE__
278#endif
279
280#define BOOST_TEST_FE_CUR_VAR BOOST_JOIN( _fe_cur_, BOOST_TEST_LINE_NUM )
281#define BOOST_TEST_FE_END_VAR BOOST_JOIN( _fe_end_, BOOST_TEST_LINE_NUM )
282#define BOOST_TEST_FE_CON_VAR BOOST_JOIN( _fe_con_, BOOST_TEST_LINE_NUM )
283
284#define BOOST_TEST_FOREACH( RefType, var, COL ) \
285if( BOOST_TEST_FE_ANY BOOST_TEST_FE_CUR_VAR = BOOST_TEST_FE_BEG( COL ) ) {} else \
286if( BOOST_TEST_FE_ANY BOOST_TEST_FE_END_VAR = BOOST_TEST_FE_END( COL ) ) {} else \
287for( bool BOOST_TEST_FE_CON_VAR = true; \
288 BOOST_TEST_FE_CON_VAR && !BOOST_TEST_FE_DONE( COL ); \
289 BOOST_TEST_FE_CON_VAR ? BOOST_TEST_FE_NEXT( COL ) : BOOST_FOREACH_NOOP( COL )) \
290 \
291 if( (BOOST_TEST_FE_CON_VAR = false, false) ) {} else \
292 for( RefType var = BOOST_TEST_FE_DEREF( COL, RefType ); \
293 !BOOST_TEST_FE_CON_VAR; BOOST_TEST_FE_CON_VAR = true ) \
294/**/
295
296#define BOOST_TEST_REVERSE_FOREACH( RefType, var, COL ) \
297if( BOOST_TEST_FE_ANY BOOST_TEST_FE_CUR_VAR = BOOST_TEST_FE_END( COL ) ) {} else \
298if( BOOST_TEST_FE_ANY BOOST_TEST_FE_END_VAR = BOOST_TEST_FE_BEG( COL ) ) {} else \
299for( bool BOOST_TEST_FE_CON_VAR = true; \
300 BOOST_TEST_FE_CON_VAR && !BOOST_TEST_FE_DONE( COL ); ) \
301 \
302 if( (BOOST_TEST_FE_CON_VAR = false, false) ) {} else \
303 if( (BOOST_TEST_FE_PREV( COL ), false) ) {} else \
304 for( RefType var = BOOST_TEST_FE_DEREF( COL, RefType ); \
305 !BOOST_TEST_FE_CON_VAR; BOOST_TEST_FE_CON_VAR = true ) \
306/**/
307
308//____________________________________________________________________________//
309
310} // namespace for_each
311} // namespace unit_test
312} // namespace boost
313
314#include <boost/test/detail/enable_warnings.hpp>
315
316#endif // BOOST_TEST_UTILS_FOREACH_HPP
317