Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/ptr_container/ptr_sequence_adapter.hpp @ 35

Last change on this file since 35 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 19.4 KB
Line 
1//
2// Boost.Pointer Container
3//
4//  Copyright Thorsten Ottosen 2003-2005. Use, modification and
5//  distribution is subject to the Boost Software License, Version
6//  1.0. (See accompanying file LICENSE_1_0.txt or copy at
7//  http://www.boost.org/LICENSE_1_0.txt)
8//
9// For more information, see http://www.boost.org/libs/ptr_container/
10//
11
12#ifndef BOOST_ptr_container_PTR_SEQUENCE_ADAPTER_HPP
13#define BOOST_ptr_container_PTR_SEQUENCE_ADAPTER_HPP
14
15#if defined(_MSC_VER) && (_MSC_VER >= 1200)
16# pragma once
17#endif
18
19
20#include <boost/ptr_container/detail/reversible_ptr_container.hpp>
21#include <boost/ptr_container/indirect_fun.hpp>
22#include <boost/ptr_container/detail/void_ptr_iterator.hpp>
23#include <boost/type_traits/remove_pointer.hpp>
24#include <boost/type_traits/is_same.hpp>
25#include <boost/type_traits/is_pointer.hpp>
26#include <boost/type_traits/is_integral.hpp>
27#include <boost/iterator/iterator_categories.hpp>
28
29
30namespace boost
31{   
32namespace ptr_container_detail
33{
34
35
36   
37   
38    template
39    < 
40        class T, 
41        class VoidPtrSeq
42    >
43    struct sequence_config
44    {
45        typedef BOOST_DEDUCED_TYPENAME remove_nullable<T>::type
46                    U;
47        typedef VoidPtrSeq
48                    void_container_type;
49
50        typedef BOOST_DEDUCED_TYPENAME VoidPtrSeq::allocator_type
51                    allocator_type;
52       
53        typedef U   value_type;
54
55        typedef void_ptr_iterator<
56                        BOOST_DEDUCED_TYPENAME VoidPtrSeq::iterator, U > 
57                    iterator;
58       
59        typedef void_ptr_iterator<
60                        BOOST_DEDUCED_TYPENAME VoidPtrSeq::const_iterator, const U >
61                    const_iterator;
62
63#ifdef BOOST_NO_SFINAE
64
65        template< class Iter >
66        static U* get_pointer( Iter i )
67        {
68            return static_cast<U*>( *i.base() );
69        }
70       
71#else
72        template< class Iter >
73        static U* get_pointer( void_ptr_iterator<Iter,U> i )
74        {
75            return static_cast<U*>( *i.base() );
76        }
77
78        template< class Iter >
79        static U* get_pointer( Iter i )
80        {
81            return &*i;
82        }
83#endif       
84
85#if defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(__MWERKS__, <= 0x3003)
86
87        template< class Iter >
88        static const U* get_const_pointer( Iter i )
89        {
90            return static_cast<const U*>( *i.base() );
91        }
92       
93#else // BOOST_NO_SFINAE
94
95#if BOOST_WORKAROUND(__MWERKS__, <= 0x3003)
96        template< class Iter >
97        static const U* get_const_pointer( void_ptr_iterator<Iter,U> i )
98        {
99            return static_cast<const U*>( *i.base() );
100        }
101#else // BOOST_WORKAROUND
102        template< class Iter >
103        static const U* get_const_pointer( void_ptr_iterator<Iter,const U> i )
104        {
105            return static_cast<const U*>( *i.base() );
106        }
107#endif // BOOST_WORKAROUND
108
109        template< class Iter >
110        static const U* get_const_pointer( Iter i )
111        {
112            return &*i;
113        }
114#endif // BOOST_NO_SFINAE
115
116        BOOST_STATIC_CONSTANT(bool, allow_null = boost::is_nullable<T>::value );
117    };
118   
119} // ptr_container_detail
120
121
122    template< class Iterator, class T >
123    inline bool is_null( void_ptr_iterator<Iterator,T> i )
124    {
125        return *i.base() == 0;
126    }
127
128
129   
130    template
131    < 
132        class T,
133        class VoidPtrSeq, 
134        class CloneAllocator = heap_clone_allocator
135    >
136    class ptr_sequence_adapter : public 
137        ptr_container_detail::reversible_ptr_container< ptr_container_detail::sequence_config<T,VoidPtrSeq>, 
138                                            CloneAllocator >
139    {
140        typedef ptr_container_detail::reversible_ptr_container< ptr_container_detail::sequence_config<T,VoidPtrSeq>,
141                                                    CloneAllocator >
142             base_type;
143       
144        typedef BOOST_DEDUCED_TYPENAME base_type::scoped_deleter scoped_deleter;
145
146        typedef ptr_sequence_adapter<T,VoidPtrSeq,CloneAllocator>                         
147            this_type;
148         
149    public:
150        typedef BOOST_DEDUCED_TYPENAME base_type::value_type  value_type; 
151        typedef BOOST_DEDUCED_TYPENAME base_type::reference   reference; 
152        typedef BOOST_DEDUCED_TYPENAME base_type::auto_type   auto_type;
153         
154        BOOST_PTR_CONTAINER_DEFINE_CONSTRUCTORS( ptr_sequence_adapter, 
155                                                 base_type )
156   
157        template< class PtrContainer >
158        ptr_sequence_adapter( std::auto_ptr<PtrContainer> clone )
159          : base_type( clone )
160        { }
161
162        template< class PtrContainer >
163        void operator=( std::auto_ptr<PtrContainer> clone )   
164        {
165            base_type::operator=( clone );
166        }
167
168        /////////////////////////////////////////////////////////////
169        // modifiers
170        /////////////////////////////////////////////////////////////
171
172        void push_back( value_type x )  // strong               
173        {
174            this->enforce_null_policy( x, "Null pointer in 'push_back()'" );
175
176            auto_type ptr( x );                // notrow
177            this->c_private().push_back( x );  // strong, commit
178            ptr.release();                     // nothrow
179        }
180
181        template< class U >
182        void push_back( std::auto_ptr<U> x )
183        {
184            push_back( x.release() );
185        }
186       
187        void push_front( value_type x )               
188        {
189            this->enforce_null_policy( x, "Null pointer in 'push_front()'" );
190
191            auto_type ptr( x );                // nothrow
192            this->c_private().push_front( x ); // strong, commit
193            ptr.release();                     // nothrow
194        }
195
196        template< class U >
197        void push_front( std::auto_ptr<U> x )
198        {
199            push_front( x.release() );
200        }
201
202        auto_type pop_back()
203        {
204            BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(), 
205                                                 bad_ptr_container_operation,
206                                          "'pop_back()' on empty container" );
207            auto_type ptr( static_cast<value_type>( 
208                         this->c_private().back() ) ); // nothrow
209            this->c_private().pop_back();              // nothrow
210            return ptr_container_detail::move( ptr );  // nothrow
211        }
212
213        auto_type pop_front()
214        {
215            BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(),
216                                                 bad_ptr_container_operation,
217                                         "'pop_front()' on empty container" ); 
218            auto_type ptr( static_cast<value_type>(
219                        this->c_private().front() ) ); // nothrow
220            this->c_private().pop_front();             // nothrow
221            return ptr_container_detail::move( ptr ); 
222        }
223       
224        reference front()       
225        { 
226            BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(), 
227                                                 bad_ptr_container_operation,
228                                    "accessing 'front()' on empty container" );
229            BOOST_ASSERT( !::boost::is_null( this->begin() ) );
230            return *this->begin(); 
231        }
232
233        const_reference front() const 
234        {
235            BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(), 
236                                                 bad_ptr_container_operation, 
237                                   "accessing 'front()' on empty container" );
238            BOOST_ASSERT( !::boost::is_null( this->begin() ) );
239            return *this->begin(); 
240        }
241
242        reference back()
243        {
244            BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(),
245                                                 bad_ptr_container_operation,
246                                    "accessing 'back()' on empty container" );
247            BOOST_ASSERT( !::boost::is_null( --this->end() ) );
248            return *--this->end(); 
249        }
250
251        const_reference back() const
252        {
253            BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(),
254                                                 bad_ptr_container_operation,
255                                    "accessing 'back()' on empty container" );
256            BOOST_ASSERT( !::boost::is_null( --this->end() ) );
257            return *--this->end(); 
258        }
259
260    public: // deque/vector inerface
261       
262        reference operator[]( size_type n ) // nothrow
263        {
264            BOOST_ASSERT( n < this->size() );
265            BOOST_ASSERT( !this->is_null( n ) );
266            return *static_cast<value_type>( this->c_private()[n] ); 
267        }
268       
269        const_reference operator[]( size_type n ) const // nothrow 
270        { 
271            BOOST_ASSERT( n < this->size() ); 
272            BOOST_ASSERT( !this->is_null( n ) );
273            return *static_cast<value_type>( this->c_private()[n] );
274        }
275       
276        reference at( size_type n )
277        {
278            BOOST_PTR_CONTAINER_THROW_EXCEPTION( n >= this->size(), bad_index, 
279                                                 "'at()' out of bounds" );
280            BOOST_ASSERT( !this->is_null( n ) );
281            return (*this)[n];
282        }
283       
284        const_reference at( size_type n ) const
285        {
286            BOOST_PTR_CONTAINER_THROW_EXCEPTION( n >= this->size(), bad_index, 
287                                                 "'at()' out of bounds" );
288            BOOST_ASSERT( !this->is_null( n ) );
289            return (*this)[n]; 
290        }
291       
292    public: // vector interface
293       
294        size_type capacity() const
295        {
296            return this->c_private().capacity();
297        }
298       
299        void reserve( size_type n )
300        {
301            this->c_private().reserve( n ); 
302        }
303
304        void reverse()
305        {
306            this->c_private().reverse(); 
307        }
308
309    public: // assign, insert, transfer
310
311        // overhead: 1 heap allocation (very cheap compared to cloning)
312        template< class InputIterator >
313        void assign( InputIterator first, InputIterator last ) // strong
314        { 
315            base_type temp( first, last );
316            this->swap( temp );
317        }
318
319        template< class Range >
320        void assign( const Range& r )
321        {
322            assign( boost::begin(r), boost::end(r ) );
323        }
324
325    private:
326        template< class I >
327        void insert_impl( iterator before, I first, I last, std::input_iterator_tag ) // strong
328        {
329            ptr_sequence_adapter temp(first,last);  // strong
330            transfer( before, temp );               // strong, commit
331        }
332
333        template< class I >
334        void insert_impl( iterator before, I first, I last, std::forward_iterator_tag ) // strong
335        {
336            if( first == last ) 
337                return;
338            scoped_deleter sd( first, last );                // strong
339            this->insert_clones_and_release( sd, before );   // strong, commit
340        }
341
342    public:
343
344        using base_type::insert;
345       
346        template< class InputIterator >
347        void insert( iterator before, InputIterator first, InputIterator last ) // strong
348        {
349            insert_impl( before, first, last, BOOST_DEDUCED_TYPENAME
350                         iterator_category<InputIterator>::type() );
351        } 
352
353#if defined(BOOST_NO_SFINAE) || BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580)
354#else
355        template< class Range >
356        BOOST_DEDUCED_TYPENAME
357        boost::disable_if< ptr_container_detail::is_pointer_or_integral<Range> >::type
358        insert( iterator before, const Range& r )
359        {
360            insert( before, boost::begin(r), boost::end(r) );
361        }
362
363#endif
364
365        template< class PtrSeqAdapter >
366        void transfer( iterator before, 
367                       BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator first, 
368                       BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator last, 
369                       PtrSeqAdapter& from ) // strong
370        {
371            BOOST_ASSERT( (void*)&from != (void*)this );
372            if( from.empty() )
373                return;
374            this->c_private().
375                insert( before.base(), 
376                        first.base(), last.base() ); // strong
377            from.c_private().erase( first.base(),
378                                    last.base() );   // nothrow
379        }
380
381        template< class PtrSeqAdapter >
382        void transfer( iterator before, 
383                       BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator object, 
384                       PtrSeqAdapter& from ) // strong
385        {
386            BOOST_ASSERT( (void*)&from != (void*)this );
387            if( from.empty() )
388                return;
389            this->c_private().
390                insert( before.base(),
391                        *object.base() );                 // strong
392            from.c_private().erase( object.base() );      // nothrow
393        }
394
395#if defined(BOOST_NO_SFINAE) || BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580)
396#else
397       
398        template< class PtrSeqAdapter, class Range >
399        BOOST_DEDUCED_TYPENAME boost::disable_if< boost::is_same< Range,
400                      BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator > >::type
401        transfer( iterator before, const Range& r, PtrSeqAdapter& from ) // strong
402        {
403            transfer( before, boost::begin(r), boost::end(r), from );
404        }
405
406#endif
407        template< class PtrSeqAdapter >
408        void transfer( iterator before, PtrSeqAdapter& from ) // strong
409        {
410            BOOST_ASSERT( (void*)&from != (void*)this );
411            if( from.empty() )
412                return;
413            this->c_private().
414                insert( before.base(),
415                        from.begin().base(), from.end().base() ); // strong
416            from.c_private().clear();                             // nothrow
417        }
418
419    public: // null functions
420         
421        bool is_null( size_type idx ) const
422        {
423            BOOST_ASSERT( idx < this->size() );
424            return this->c_private()[idx] == 0;
425        }
426
427    public: // algorithms
428
429        void sort( iterator first, iterator last )
430        {
431            sort( first, last, std::less<T>() );
432        }
433       
434        void sort()
435        {
436            sort( this->begin(), this->end() );
437        }
438
439        template< class Compare >
440        void sort( iterator first, iterator last, Compare comp )
441        {
442            BOOST_ASSERT( first <= last && "out of range sort()" );
443            BOOST_ASSERT( this->begin() <= first && "out of range sort()" );
444            BOOST_ASSERT( last <= this->end() && "out of range sort()" ); 
445            // some static assert on the arguments of the comparison
446            std::sort( first.base(), last.base(), 
447                       void_ptr_indirect_fun<Compare,T>(comp) );
448        }
449       
450        template< class Compare >
451        void sort( Compare comp )
452        {
453            sort( this->begin(), this->end(), comp );
454        }
455       
456        void unique( iterator first, iterator last )
457        {
458            unique( first, last, std::equal_to<T>() );
459        }
460       
461        void unique()
462        {
463            unique( this->begin(), this->end() );
464        }
465
466    private:
467        struct is_not_zero_ptr
468        {
469            template< class U >
470            bool operator()( const U* r ) const
471            {
472                return r != 0;
473            }
474        };
475
476        void compact_and_erase_nulls( iterator first, iterator last ) // nothrow
477        {
478           
479            typename base_type::ptr_iterator p = std::stable_partition( 
480                                                    first.base(), 
481                                                    last.base(), 
482                                                    is_not_zero_ptr() );
483            this->c_private().erase( p, this->end().base() );
484           
485        }
486
487        void range_check_impl( iterator first, iterator last, 
488                               std::bidirectional_iterator_tag )
489        { /* do nothing */ }
490
491        void range_check_impl( iterator first, iterator last,
492                               std::random_access_iterator_tag )
493        {
494            BOOST_ASSERT( first <= last && "out of range unique()/erase_if()" );
495            BOOST_ASSERT( this->begin() <= first && "out of range unique()/erase_if()" );
496            BOOST_ASSERT( last <= this->end() && "out of range unique()/erase_if)(" );             
497        }
498       
499        void range_check( iterator first, iterator last )
500        {
501            range_check_impl( first, last, 
502                              BOOST_DEDUCED_TYPENAME iterator_category<iterator>::type() );
503        }
504       
505    public:
506       
507        template< class Compare >
508        void unique( iterator first, iterator last, Compare comp )
509        {
510            range_check(first,last);
511           
512            iterator prev = first;
513            iterator next = first;
514            ++next;
515            for( ; next != last; ++next )
516            {
517                BOOST_ASSERT( !::boost::is_null(prev) );
518                BOOST_ASSERT( !::boost::is_null(next) );
519                if( comp( *prev, *next ) )
520                {
521                    this->remove( next ); // delete object
522                    *next.base() = 0;     // mark pointer as deleted
523                }
524                else
525                {
526                    prev = next;
527                }
528                // ++next
529            }
530
531            compact_and_erase_nulls( first, last );
532        }
533       
534        template< class Compare >
535        void unique( Compare comp )
536        {
537            unique( this->begin(), this->end(), comp );
538        }
539
540        template< class Pred >
541        void erase_if( iterator first, iterator last, Pred pred )
542        {
543            range_check(first,last);
544
545            iterator next = first; 
546            for( ; next != last; ++next )
547            {
548                BOOST_ASSERT( !::boost::is_null(next) );
549                if( pred( *next ) )
550                {
551                    this->remove( next ); // delete object
552                    *next.base() = 0;     // mark pointer as deleted
553                }
554            }
555
556            compact_and_erase_nulls( first, last );
557        }
558       
559        template< class Pred >
560        void erase_if( Pred pred )
561        {
562            erase_if( this->begin(), this->end(), pred );
563        }
564
565
566        void merge( iterator first, iterator last, 
567                    ptr_sequence_adapter& from )
568        {
569             merge( first, last, from, std::less<T>() );
570        }
571       
572        template< class BinPred >
573        void merge( iterator first, iterator last, 
574                    ptr_sequence_adapter& from, BinPred pred )
575        {
576            void_ptr_indirect_fun<BinPred,T>  bin_pred(pred);
577            size_type                         current_size = this->size(); 
578            this->transfer( this->end(), first, last, from );
579            typename base_type::ptr_iterator middle = this->begin().base();
580            std::advance(middle,current_size); 
581            std::inplace_merge( this->begin().base(),
582                                middle,
583                                this->end().base(),
584                                bin_pred );
585        }
586       
587        void merge( ptr_sequence_adapter& r )
588        {
589            merge( r, std::less<T>() );
590            BOOST_ASSERT( r.empty() );
591        }
592       
593        template< class BinPred >
594        void merge( ptr_sequence_adapter& r, BinPred pred )
595        {
596            merge( r.begin(), r.end(), r, pred );
597            BOOST_ASSERT( r.empty() );   
598        }
599       
600    };
601
602
603} // namespace 'boost' 
604
605#endif
Note: See TracBrowser for help on using the repository browser.