1 // Boost.Range library
2 //
3 //  Copyright Neil Groves & Thorsten Ottosen & Pavol Droba 2003-2004.
4 //  Use, modification and distribution is subject to the Boost Software
5 //  License, Version 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 #ifndef BOOST_RANGE_ITERATOR_RANGE_CORE_HPP_INCLUDED
11 #define BOOST_RANGE_ITERATOR_RANGE_CORE_HPP_INCLUDED
12 
13 #include <boost/config.hpp> // Define __STL_CONFIG_H, if appropriate.
14 #include <boost/detail/workaround.hpp>
15 
16 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
17     #pragma warning( push )
18     #pragma warning( disable : 4996 )
19 #endif
20 
21 #include <boost/assert.hpp>
22 #include <boost/iterator/iterator_traits.hpp>
23 #include <boost/iterator/iterator_facade.hpp>
24 #include <boost/type_traits/is_abstract.hpp>
25 #include <boost/type_traits/is_pointer.hpp>
26 #include <boost/range/functions.hpp>
27 #include <boost/range/iterator.hpp>
28 #include <boost/range/difference_type.hpp>
29 #include <boost/range/algorithm/equal.hpp>
30 #include <boost/range/detail/safe_bool.hpp>
31 #include <boost/utility/enable_if.hpp>
32 #include <iterator>
33 #include <algorithm>
34 #include <cstddef>
35 
36 /*! \file
37     Defines the \c iterator_class and related functions.
38     \c iterator_range is a simple wrapper of iterator pair idiom. It provides
39     a rich subset of Container interface.
40 */
41 
42 
43 namespace boost
44 {
45     namespace iterator_range_detail
46     {
47         //
48         // The functions adl_begin and adl_end are implemented in a separate
49         // class for gcc-2.9x
50         //
51         template<class IteratorT>
52         struct iterator_range_impl {
53             template< class ForwardRange >
adl_beginboost::iterator_range_detail::iterator_range_impl54             static IteratorT adl_begin( ForwardRange& r )
55             {
56                 return static_cast<IteratorT>( boost::begin( r ) );
57             }
58 
59             template< class ForwardRange >
adl_endboost::iterator_range_detail::iterator_range_impl60             static IteratorT adl_end( ForwardRange& r )
61             {
62                 return static_cast<IteratorT>( boost::end( r ) );
63             }
64         };
65 
66         template< class Left, class Right >
less_than(const Left & l,const Right & r)67         inline bool less_than( const Left& l, const Right& r )
68         {
69             return std::lexicographical_compare( boost::begin(l),
70                                                  boost::end(l),
71                                                  boost::begin(r),
72                                                  boost::end(r) );
73         }
74 
75         template< class Left, class Right >
greater_than(const Left & l,const Right & r)76         inline bool greater_than( const Left& l, const Right& r )
77         {
78             return less_than(r,l);
79         }
80 
81         template< class Left, class Right >
less_or_equal_than(const Left & l,const Right & r)82         inline bool less_or_equal_than( const Left& l, const Right& r )
83         {
84             return !iterator_range_detail::less_than(r,l);
85         }
86 
87         template< class Left, class Right >
greater_or_equal_than(const Left & l,const Right & r)88         inline bool greater_or_equal_than( const Left& l, const Right& r )
89         {
90             return !iterator_range_detail::less_than(l,r);
91         }
92 
93         // This version is maintained since it is used in other boost libraries
94         // such as Boost.Assign
95         template< class Left, class Right >
equal(const Left & l,const Right & r)96         inline bool equal(const Left& l, const Right& r)
97         {
98             return boost::equal(l, r);
99         }
100 
101         struct range_tag { };
102         struct const_range_tag { };
103     }
104 
105 //  iterator range template class -----------------------------------------//
106 
107         //! iterator_range class
108         /*!
109             An \c iterator_range delimits a range in a sequence by beginning and ending iterators.
110             An iterator_range can be passed to an algorithm which requires a sequence as an input.
111             For example, the \c toupper() function may be used most frequently on strings,
112             but can also be used on iterator_ranges:
113 
114             \code
115                 boost::tolower( find( s, "UPPERCASE STRING" ) );
116             \endcode
117 
118             Many algorithms working with sequences take a pair of iterators,
119             delimiting a working range, as an arguments. The \c iterator_range class is an
120             encapsulation of a range identified by a pair of iterators.
121             It provides a collection interface,
122             so it is possible to pass an instance to an algorithm requiring a collection as an input.
123         */
124         template<class IteratorT>
125         class iterator_range
126         {
127             typedef range_detail::safe_bool< IteratorT iterator_range<IteratorT>::* > safe_bool_t;
128         protected: // Used by sub_range
129             //! implementation class
130             typedef iterator_range_detail::iterator_range_impl<IteratorT> impl;
131         public:
132             //! this type
133             typedef iterator_range<IteratorT> type;
134             typedef BOOST_DEDUCED_TYPENAME safe_bool_t::unspecified_bool_type unspecified_bool_type;
135             //BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(value_type);
136 
137             //! Encapsulated value type
138             typedef BOOST_DEDUCED_TYPENAME
139                 iterator_value<IteratorT>::type value_type;
140 
141             //! Difference type
142             typedef BOOST_DEDUCED_TYPENAME
143                 iterator_difference<IteratorT>::type difference_type;
144 
145             //! Size type
146             typedef std::size_t size_type; // note: must be unsigned
147 
148             //! This type
149             typedef iterator_range<IteratorT> this_type;
150 
151             //! Reference type
152             //
153             // Needed because value-type is the same for
154             // const and non-const iterators
155             //
156             typedef BOOST_DEDUCED_TYPENAME
157                 iterator_reference<IteratorT>::type reference;
158 
159             //! const_iterator type
160             /*!
161                 There is no distinction between const_iterator and iterator.
162                 These typedefs are provides to fulfill container interface
163             */
164             typedef IteratorT const_iterator;
165             //! iterator type
166             typedef IteratorT iterator;
167 
168         private: // for return value of operator()()
169             typedef BOOST_DEDUCED_TYPENAME
170                 boost::mpl::if_< boost::is_abstract<value_type>,
171                                  reference, value_type >::type abstract_value_type;
172 
173         public:
iterator_range()174             iterator_range() : m_Begin( iterator() ), m_End( iterator() )
175             { }
176 
177             //! Constructor from a pair of iterators
178             template< class Iterator >
iterator_range(Iterator Begin,Iterator End)179             iterator_range( Iterator Begin, Iterator End ) :
180                 m_Begin(Begin), m_End(End)
181             {}
182 
183             //! Constructor from a Range
184             template< class Range >
iterator_range(const Range & r)185             iterator_range( const Range& r ) :
186                 m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
187             {}
188 
189             //! Constructor from a Range
190             template< class Range >
iterator_range(Range & r)191             iterator_range( Range& r ) :
192                 m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
193             {}
194 
195             //! Constructor from a Range
196             template< class Range >
iterator_range(const Range & r,iterator_range_detail::const_range_tag)197             iterator_range( const Range& r, iterator_range_detail::const_range_tag ) :
198                 m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
199             {}
200 
201             //! Constructor from a Range
202             template< class Range >
iterator_range(Range & r,iterator_range_detail::range_tag)203             iterator_range( Range& r, iterator_range_detail::range_tag ) :
204                 m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
205             {}
206 
207             #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
operator =(const this_type & r)208             this_type& operator=( const this_type& r )
209             {
210                 m_Begin  = r.begin();
211                 m_End    = r.end();
212                 return *this;
213             }
214             #endif
215 
216             template< class Iterator >
operator =(const iterator_range<Iterator> & r)217             iterator_range& operator=( const iterator_range<Iterator>& r )
218             {
219                 m_Begin  = r.begin();
220                 m_End    = r.end();
221                 return *this;
222             }
223 
224             template< class ForwardRange >
operator =(ForwardRange & r)225             iterator_range& operator=( ForwardRange& r )
226             {
227                 m_Begin  = impl::adl_begin( r );
228                 m_End    = impl::adl_end( r );
229                 return *this;
230             }
231 
232             template< class ForwardRange >
operator =(const ForwardRange & r)233             iterator_range& operator=( const ForwardRange& r )
234             {
235                 m_Begin  = impl::adl_begin( r );
236                 m_End    = impl::adl_end( r );
237                 return *this;
238             }
239 
begin() const240             IteratorT begin() const
241             {
242                 return m_Begin;
243             }
244 
end() const245             IteratorT end() const
246             {
247                 return m_End;
248             }
249 
size() const250             difference_type size() const
251             {
252                 return m_End - m_Begin;
253             }
254 
empty() const255             bool empty() const
256             {
257                 return m_Begin == m_End;
258             }
259 
operator unspecified_bool_type() const260             operator unspecified_bool_type() const
261             {
262                 return safe_bool_t::to_unspecified_bool(m_Begin != m_End, &iterator_range::m_Begin);
263             }
264 
operator !() const265             bool operator!() const
266             {
267                 return empty();
268             }
269 
equal(const iterator_range & r) const270             bool equal( const iterator_range& r ) const
271             {
272                 return m_Begin == r.m_Begin && m_End == r.m_End;
273             }
274 
275 
276 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
277 
operator ==(const iterator_range & r) const278             bool operator==( const iterator_range& r ) const
279             {
280                 return boost::equal( *this, r );
281             }
282 
operator !=(const iterator_range & r) const283             bool operator!=( const iterator_range& r ) const
284             {
285                 return !operator==(r);
286             }
287 
operator <(const iterator_range & r) const288            bool operator<( const iterator_range& r ) const
289            {
290                return iterator_range_detail::less_than( *this, r );
291            }
292 
operator >(const iterator_range & r) const293            bool operator>( const iterator_range& r ) const
294            {
295                return iterator_range_detail::greater_than( *this, r );
296            }
297 
operator <=(const iterator_range & r) const298            bool operator<=( const iterator_range& r ) const
299            {
300                return iterator_range_detail::less_or_equal_than( *this, r );
301            }
302 
operator >=(const iterator_range & r) const303            bool operator>=( const iterator_range& r ) const
304            {
305                return iterator_range_detail::greater_or_equal_than( *this, r );
306            }
307 
308 #endif
309 
310         public: // convenience
front() const311            reference front() const
312            {
313                BOOST_ASSERT( !empty() );
314                return *m_Begin;
315            }
316 
back() const317            reference back() const
318            {
319                BOOST_ASSERT( !empty() );
320                IteratorT last( m_End );
321                return *--last;
322            }
323 
324            // pop_front() - added to model the SinglePassRangePrimitiveConcept
pop_front()325            void pop_front()
326            {
327                BOOST_ASSERT( !empty() );
328                ++m_Begin;
329            }
330 
331            // pop_back() - added to model the BidirectionalRangePrimitiveConcept
pop_back()332            void pop_back()
333            {
334                BOOST_ASSERT( !empty() );
335                --m_End;
336            }
337 
operator [](difference_type at) const338            reference operator[]( difference_type at ) const
339            {
340                BOOST_ASSERT( at >= 0 && at < size() );
341                return m_Begin[at];
342            }
343 
344            //
345            // When storing transform iterators, operator[]()
346            // fails because it returns by reference. Therefore
347            // operator()() is provided for these cases.
348            //
operator ()(difference_type at) const349            abstract_value_type operator()( difference_type at ) const
350            {
351                BOOST_ASSERT( at >= 0 && at < size() );
352                return m_Begin[at];
353            }
354 
advance_begin(difference_type n)355            iterator_range& advance_begin( difference_type n )
356            {
357                std::advance( m_Begin, n );
358                return *this;
359            }
360 
advance_end(difference_type n)361            iterator_range& advance_end( difference_type n )
362            {
363                std::advance( m_End, n );
364                return *this;
365            }
366 
367         private:
368             // begin and end iterators
369             IteratorT m_Begin;
370             IteratorT m_End;
371 
372         protected:
373             //
374             // Allow subclasses an easy way to access the
375             // base type
376             //
377             typedef iterator_range iterator_range_;
378         };
379 
380 //  iterator range free-standing operators ---------------------------//
381 
382         /////////////////////////////////////////////////////////////////////
383         // comparison operators
384         /////////////////////////////////////////////////////////////////////
385 
386         template< class IteratorT, class ForwardRange >
operator ==(const ForwardRange & l,const iterator_range<IteratorT> & r)387         inline bool operator==( const ForwardRange& l,
388                                 const iterator_range<IteratorT>& r )
389         {
390             return boost::equal( l, r );
391         }
392 
393         template< class IteratorT, class ForwardRange >
operator !=(const ForwardRange & l,const iterator_range<IteratorT> & r)394         inline bool operator!=( const ForwardRange& l,
395                                 const iterator_range<IteratorT>& r )
396         {
397             return !boost::equal( l, r );
398         }
399 
400         template< class IteratorT, class ForwardRange >
operator <(const ForwardRange & l,const iterator_range<IteratorT> & r)401         inline bool operator<( const ForwardRange& l,
402                                const iterator_range<IteratorT>& r )
403         {
404             return iterator_range_detail::less_than( l, r );
405         }
406 
407         template< class IteratorT, class ForwardRange >
operator <=(const ForwardRange & l,const iterator_range<IteratorT> & r)408         inline bool operator<=( const ForwardRange& l,
409                                 const iterator_range<IteratorT>& r )
410         {
411             return iterator_range_detail::less_or_equal_than( l, r );
412         }
413 
414         template< class IteratorT, class ForwardRange >
operator >(const ForwardRange & l,const iterator_range<IteratorT> & r)415         inline bool operator>( const ForwardRange& l,
416                                const iterator_range<IteratorT>& r )
417         {
418             return iterator_range_detail::greater_than( l, r );
419         }
420 
421         template< class IteratorT, class ForwardRange >
operator >=(const ForwardRange & l,const iterator_range<IteratorT> & r)422         inline bool operator>=( const ForwardRange& l,
423                                 const iterator_range<IteratorT>& r )
424         {
425             return iterator_range_detail::greater_or_equal_than( l, r );
426         }
427 
428 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
429 #else
430         template< class Iterator1T, class Iterator2T >
operator ==(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)431         inline bool operator==( const iterator_range<Iterator1T>& l,
432                                 const iterator_range<Iterator2T>& r )
433         {
434             return boost::equal( l, r );
435         }
436 
437         template< class IteratorT, class ForwardRange >
operator ==(const iterator_range<IteratorT> & l,const ForwardRange & r)438         inline bool operator==( const iterator_range<IteratorT>& l,
439                                 const ForwardRange& r )
440         {
441             return boost::equal( l, r );
442         }
443 
444 
445         template< class Iterator1T, class Iterator2T >
operator !=(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)446         inline bool operator!=( const iterator_range<Iterator1T>& l,
447                                 const iterator_range<Iterator2T>& r )
448         {
449             return !boost::equal( l, r );
450         }
451 
452         template< class IteratorT, class ForwardRange >
operator !=(const iterator_range<IteratorT> & l,const ForwardRange & r)453         inline bool operator!=( const iterator_range<IteratorT>& l,
454                                 const ForwardRange& r )
455         {
456             return !boost::equal( l, r );
457         }
458 
459 
460         template< class Iterator1T, class Iterator2T >
operator <(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)461         inline bool operator<( const iterator_range<Iterator1T>& l,
462                                const iterator_range<Iterator2T>& r )
463         {
464             return iterator_range_detail::less_than( l, r );
465         }
466 
467         template< class IteratorT, class ForwardRange >
operator <(const iterator_range<IteratorT> & l,const ForwardRange & r)468         inline bool operator<( const iterator_range<IteratorT>& l,
469                                const ForwardRange& r )
470         {
471             return iterator_range_detail::less_than( l, r );
472         }
473 
474         template< class Iterator1T, class Iterator2T >
operator <=(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)475         inline bool operator<=( const iterator_range<Iterator1T>& l,
476                                 const iterator_range<Iterator2T>& r )
477         {
478             return iterator_range_detail::less_or_equal_than( l, r );
479         }
480 
481         template< class IteratorT, class ForwardRange >
operator <=(const iterator_range<IteratorT> & l,const ForwardRange & r)482         inline bool operator<=( const iterator_range<IteratorT>& l,
483                                 const ForwardRange& r )
484         {
485             return iterator_range_detail::less_or_equal_than( l, r );
486         }
487 
488         template< class Iterator1T, class Iterator2T >
operator >(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)489         inline bool operator>( const iterator_range<Iterator1T>& l,
490                                const iterator_range<Iterator2T>& r )
491         {
492             return iterator_range_detail::greater_than( l, r );
493         }
494 
495         template< class IteratorT, class ForwardRange >
operator >(const iterator_range<IteratorT> & l,const ForwardRange & r)496         inline bool operator>( const iterator_range<IteratorT>& l,
497                                const ForwardRange& r )
498         {
499             return iterator_range_detail::greater_than( l, r );
500         }
501 
502         template< class Iterator1T, class Iterator2T >
operator >=(const iterator_range<Iterator1T> & l,const iterator_range<Iterator2T> & r)503         inline bool operator>=( const iterator_range<Iterator1T>& l,
504                                 const iterator_range<Iterator2T>& r )
505         {
506             return iterator_range_detail::greater_or_equal_than( l, r );
507         }
508 
509         template< class IteratorT, class ForwardRange >
operator >=(const iterator_range<IteratorT> & l,const ForwardRange & r)510         inline bool operator>=( const iterator_range<IteratorT>& l,
511                                 const ForwardRange& r )
512         {
513             return iterator_range_detail::greater_or_equal_than( l, r );
514         }
515 
516 #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
517 
518 //  iterator range utilities -----------------------------------------//
519 
520         //! iterator_range construct helper
521         /*!
522             Construct an \c iterator_range from a pair of iterators
523 
524             \param Begin A begin iterator
525             \param End An end iterator
526             \return iterator_range object
527         */
528         template< typename IteratorT >
529         inline iterator_range< IteratorT >
make_iterator_range(IteratorT Begin,IteratorT End)530         make_iterator_range( IteratorT Begin, IteratorT End )
531         {
532             return iterator_range<IteratorT>( Begin, End );
533         }
534 
535 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
536 
537         template< typename Range >
538         inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
make_iterator_range(Range & r)539         make_iterator_range( Range& r )
540         {
541             return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
542                 ( boost::begin( r ), boost::end( r ) );
543         }
544 
545 #else
546         //! iterator_range construct helper
547         /*!
548             Construct an \c iterator_range from a \c Range containing the begin
549             and end iterators.
550         */
551         template< class ForwardRange >
552         inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type >
make_iterator_range(ForwardRange & r)553         make_iterator_range( ForwardRange& r )
554         {
555            return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type >
556                 ( r, iterator_range_detail::range_tag() );
557         }
558 
559         template< class ForwardRange >
560         inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type >
make_iterator_range(const ForwardRange & r)561         make_iterator_range( const ForwardRange& r )
562         {
563            return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type >
564                 ( r, iterator_range_detail::const_range_tag() );
565         }
566 
567 #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
568 
569         namespace iterator_range_detail
570         {
571             template< class Range >
572             inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
make_range_impl(Range & r,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end)573             make_range_impl( Range& r,
574                              BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
575                              BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
576             {
577                 //
578                 // Not worth the effort
579                 //
580                 //if( advance_begin == 0 && advance_end == 0 )
581                 //    return make_iterator_range( r );
582                 //
583 
584                 BOOST_DEDUCED_TYPENAME range_iterator<Range>::type
585                     new_begin = boost::begin( r ),
586                     new_end   = boost::end( r );
587                 std::advance( new_begin, advance_begin );
588                 std::advance( new_end, advance_end );
589                 return make_iterator_range( new_begin, new_end );
590             }
591         }
592 
593 #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
594 
595         template< class Range >
596         inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
make_iterator_range(Range & r,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end)597         make_iterator_range( Range& r,
598                     BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
599                     BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
600         {
601             //BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" );
602             return iterator_range_detail::make_range_impl( r, advance_begin, advance_end );
603         }
604 
605 #else
606 
607         template< class Range >
608         inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
make_iterator_range(Range & r,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end)609         make_iterator_range( Range& r,
610                     BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
611                     BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
612         {
613             //BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" );
614             return iterator_range_detail::make_range_impl( r, advance_begin, advance_end );
615         }
616 
617         template< class Range >
618         inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const Range>::type >
make_iterator_range(const Range & r,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end)619         make_iterator_range( const Range& r,
620                     BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
621                     BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
622         {
623             //BOOST_ASSERT( advance_begin - advance_end <= size(r) && "creating invalid range" );
624             return iterator_range_detail::make_range_impl( r, advance_begin, advance_end );
625         }
626 
627 #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
628 
629         //! copy a range into a sequence
630         /*!
631             Construct a new sequence of the specified type from the elements
632             in the given range
633 
634             \param Range An input range
635             \return New sequence
636         */
637         template< typename SeqT, typename Range >
copy_range(const Range & r)638         inline SeqT copy_range( const Range& r )
639         {
640             return SeqT( boost::begin( r ), boost::end( r ) );
641         }
642 
643 } // namespace 'boost'
644 
645 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
646     #pragma warning( pop )
647 #endif
648 
649 #endif
650 
651