~yade-dev/yade/0.80

« back to all changes in this revision

Viewing changes to py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/container_proxy.hpp

  • Committer: Anton Gladky
  • Date: 2012-05-02 21:50:42 UTC
  • Revision ID: gladky.anton@gmail.com-20120502215042-v1fa9r65usqe7kfk
0.80.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (c) 2003 Raoul M. Gough
 
2
//
 
3
// Use, modification and distribution is subject to the Boost Software
 
4
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
 
5
// at http://www.boost.org/LICENSE_1_0.txt)
 
6
//
 
7
// Header file container_proxy.hpp
 
8
//
 
9
// A container-wrapper that provides Python-style reference semantics
 
10
// for values stored in vector-like containers via element proxies.
 
11
//
 
12
// Class invariant:
 
13
//   size() == m_proxies.size()
 
14
//   for 0 <= i < size()
 
15
//     m_proxies[i].get() != 0
 
16
//     m_proxies[i]->owner() == this
 
17
//     m_proxies[i]->index() == i
 
18
//     m_proxies[i]->m_element_ptr.get() == 0
 
19
//
 
20
// History
 
21
// =======
 
22
// 2003/ 8/26   rmg     File creation
 
23
// 2003/10/23   rmg     Change pointer container from map to sequence
 
24
// 2008/12/08   Roman   Change indexing suite layout
 
25
//
 
26
// $Id: container_proxy.hpp,v 1.1.2.28 2004/02/08 18:57:42 raoulgough Exp $
 
27
//
 
28
 
 
29
#ifndef BOOST_PYTHON_INDEXING_CONTAINER_PROXY_HPP
 
30
#define BOOST_PYTHON_INDEXING_CONTAINER_PROXY_HPP
 
31
 
 
32
#include <indexing_suite/proxy_iterator.hpp>
 
33
#include <indexing_suite/shared_proxy_impl.hpp>
 
34
#include <indexing_suite/element_proxy.hpp>
 
35
#include <indexing_suite/element_proxy_traits.hpp>
 
36
#include <indexing_suite/workaround.hpp>
 
37
#include <indexing_suite/methods.hpp>
 
38
 
 
39
#include <vector>
 
40
#include <cassert>
 
41
#include <boost/shared_ptr.hpp>
 
42
#include <boost/mpl/apply.hpp>
 
43
#include <boost/iterator/iterator_traits.hpp>
 
44
#include <indexing_suite/container_traits.hpp>
 
45
#include <indexing_suite/container_suite.hpp>
 
46
#include <indexing_suite/algorithms.hpp>
 
47
 
 
48
namespace boost { namespace python { namespace indexing {
 
49
 
 
50
  template<typename T> struct identity {
 
51
    typedef T held_type;
 
52
 
 
53
    static T &       get(T &       obj) { return obj; }
 
54
    static T const & get(T const & obj) { return obj; }
 
55
 
 
56
    static T    create ()                     { return T(); }
 
57
    static T    copy   (T const &copy)        { return copy; }
 
58
    static void assign (T &to, T const &from) { to = from; }
 
59
    static void pre_destruction (T &)         { }
 
60
    static void swap   (T &one, T &two)       { std::swap (one, two); }
 
61
  };
 
62
 
 
63
  template<typename P> struct deref {
 
64
    typedef P held_type;
 
65
 
 
66
    typedef typename boost::iterator_value<P>::type     value;
 
67
 
 
68
    static value &       get (P &       ptr)  { return *ptr; }
 
69
    static value const & get (P const & ptr)  { return *ptr; }
 
70
 
 
71
    static P    create ()                     { return P(); }
 
72
    static P    copy   (P const &copy)        { return copy; }
 
73
    static void assign (P &to, P const &from) { to = from; }
 
74
    static void pre_destruction (P &)         { }
 
75
    static void swap   (P &one, P &two)       { std::swap (one, two); }
 
76
  };
 
77
 
 
78
  struct vector_generator {
 
79
    // Generates vector type for any element type with default allocator
 
80
    template<typename Element> struct apply {
 
81
      typedef std::vector<Element> type;
 
82
    };
 
83
  };
 
84
 
 
85
#if BOOST_WORKAROUND (BOOST_MSVC, == 1200)
 
86
  // Early template instantiation (ETI) workaround
 
87
  namespace detail {
 
88
    template<typename Container> struct msvc6_iterator {
 
89
      typedef Container::iterator type;
 
90
    };
 
91
 
 
92
    template<> struct msvc6_iterator<int> {
 
93
      typedef int *type;
 
94
    };
 
95
  }
 
96
#endif
 
97
 
 
98
  template<class Container,
 
99
           class Holder = identity<Container>,
 
100
           class Generator = vector_generator>
 
101
  class container_proxy
 
102
  {
 
103
    typedef container_proxy<Container, Holder, Generator> self_type;
 
104
    typedef typename Container::iterator raw_iterator;
 
105
    typedef ::boost::detail::iterator_traits<raw_iterator> raw_iterator_traits;
 
106
 
 
107
#if !defined (BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
 
108
    template<class C> friend class shared_proxy_impl;
 
109
    template<class C, typename E, typename T, typename S, typename I>
 
110
        friend class proxy_iterator;
 
111
#endif
 
112
 
 
113
  public:
 
114
    typedef typename Holder::held_type held_type;
 
115
 
 
116
    typedef typename Container::size_type size_type;
 
117
    typedef typename Container::difference_type difference_type;
 
118
 
 
119
    typedef shared_proxy_impl<self_type> shared_proxy;
 
120
 
 
121
    typedef typename Container::value_type raw_value_type;
 
122
 
 
123
    typedef element_proxy<self_type> value_type;
 
124
    typedef value_type               reference;  // Already has ref. semantics
 
125
 
 
126
    typedef const_element_proxy<self_type> const_value_type;
 
127
    typedef const_value_type               const_reference; // Ref. semantics
 
128
 
 
129
    typedef proxy_iterator <self_type, value_type, raw_iterator_traits,
 
130
        size_type, raw_iterator> iterator;
 
131
    typedef iterator const_iterator; // No const_iterator yet implemented
 
132
 
 
133
  public:
 
134
    // Constructors
 
135
    template<typename Iter> container_proxy (Iter start, Iter finish)
 
136
      // Define inline for MSVC6 compatibility
 
137
      : m_held_obj (Holder::create()),
 
138
      m_proxies ()
 
139
    {
 
140
      insert (begin(), start, finish);
 
141
    }
 
142
 
 
143
    container_proxy ();
 
144
    explicit container_proxy (held_type const &h);
 
145
 
 
146
    container_proxy (container_proxy const &);
 
147
    container_proxy &operator= (container_proxy const &);
 
148
    ~container_proxy ();
 
149
 
 
150
    Container const &raw_container() const;   // OK to expose const reference
 
151
 
 
152
    reference       at (size_type index);
 
153
    const_reference at (size_type index) const;
 
154
 
 
155
    reference       operator[] (size_type index)       { return at(index); }
 
156
    const_reference operator[] (size_type index) const { return at(index); }
 
157
 
 
158
    size_type size ()     const { return raw_container().size(); }
 
159
    size_type capacity () const { return raw_container().capacity(); }
 
160
    void reserve (size_type s);
 
161
 
 
162
  public:
 
163
    iterator begin() { return iterator (this, static_cast<size_type>(0)); }
 
164
    iterator end() { return iterator (this, raw_container().size()); }
 
165
 
 
166
    iterator erase (iterator);
 
167
    iterator erase (iterator, iterator);
 
168
    iterator insert (iterator, raw_value_type const &);
 
169
 
 
170
    template<typename Iter> void insert (iterator iter, Iter from, Iter to)
 
171
      // Define here for MSVC6 compatibility
 
172
    {
 
173
      // Forward insertion to the right overloaded version
 
174
      typedef typename BOOST_ITERATOR_CATEGORY<Iter>::type category;
 
175
      insert (iter, from, to, category());
 
176
    }
 
177
 
 
178
    void push_back (raw_value_type const &copy) { insert (end(), copy); }
 
179
 
 
180
    value_type pop_back () {
 
181
      value_type result = at (size() - 1);
 
182
      erase (end() - 1);
 
183
      return result;
 
184
    }
 
185
 
 
186
  public:
 
187
    // These functions are useful only when client code has direct
 
188
    // non-const acccess to the raw container (e.g. via an indirect
 
189
    // holder supplied to our constructor). Any code that directly
 
190
    // modifies the contents of the raw container (by replacing,
 
191
    // inserting or erasing elements) must notify the container_proxy.
 
192
 
 
193
    void detach_proxy (size_type index);
 
194
    void detach_proxies (size_type from, size_type to);
 
195
    // Call before overwriting element(s) in the raw container
 
196
 
 
197
    void prepare_erase (size_type from, size_type to);
 
198
    // Call before erasing elements directly from the raw container
 
199
 
 
200
    void notify_insertion (size_type from, size_type to);
 
201
    // Call after inserting elements directly into the raw container
 
202
 
 
203
  public:
 
204
    // Convenient replacement of elements (automatic proxy detachment)
 
205
    void replace (size_type index, raw_value_type const &);
 
206
    //    template<typename Iter> void replace (size_type index, Iter, Iter);
 
207
 
 
208
    void swap_elements (size_type index1, size_type index2);
 
209
 
 
210
    bool is_valid () const; // Check the class invariant (for testing purposes)
 
211
 
 
212
  private:
 
213
    // Overloads for insertions with/without useful std::distance
 
214
    template<typename Iter>
 
215
    void insert (iterator iter, Iter from, Iter to, std::forward_iterator_tag)
 
216
      // Define here for MSVC6 compatibility
 
217
    {
 
218
      assert (iter.ptr == this);
 
219
      size_type count = std::distance (from, to);
 
220
 
 
221
      // Add empty proxy pointers for the new value(s) (could throw)
 
222
      m_proxies.insert (m_proxies.begin() + iter.index, count, pointer_impl());
 
223
 
 
224
      try
 
225
        {
 
226
          // Insert the new element(s) into the real container (could throw)
 
227
          raw_container().insert(
 
228
              raw_container().begin() + iter.index,
 
229
              from,
 
230
              to);
 
231
 
 
232
          try
 
233
            {
 
234
              // Create new proxies for the new elements (could throw)
 
235
              write_proxies (iter.index, iter.index + count);
 
236
            }
 
237
 
 
238
          catch (...)
 
239
            {
 
240
              raw_container().erase(
 
241
                  raw_container().begin() + iter.index,
 
242
                  raw_container().begin() + iter.index + count);
 
243
 
 
244
              throw;
 
245
            }
 
246
        }
 
247
 
 
248
      catch (...)
 
249
        {
 
250
          m_proxies.erase(
 
251
              m_proxies.begin() + iter.index,
 
252
              m_proxies.begin() + iter.index + count);
 
253
 
 
254
          throw;
 
255
        }
 
256
 
 
257
      // Adjust any proxies after the inserted elements (nothrow)
 
258
      adjust_proxies(
 
259
          m_proxies.begin() + iter.index + count,
 
260
          m_proxies.end(),
 
261
          static_cast<difference_type> (count));
 
262
    }
 
263
 
 
264
    template<typename Iter>
 
265
    void insert (iterator iter, Iter from, Iter to, std::input_iterator_tag)
 
266
      // Define here for MSVC6 compatibility
 
267
    {
 
268
      // insert overload for iterators where we *can't* get distance()
 
269
      // so just insert elements one at a time
 
270
      while (from != to)
 
271
        {
 
272
          iter = insert (iter, *from++) + 1;
 
273
        }
 
274
    }
 
275
 
 
276
  private:
 
277
    typedef boost::shared_ptr<shared_proxy> pointer_impl;
 
278
 
 
279
    typedef typename mpl::apply1<Generator, pointer_impl>::type
 
280
      pointer_container;
 
281
 
 
282
#if BOOST_WORKAROUND (BOOST_MSVC, == 1200)
 
283
    typedef detail::msvc6_iterator<pointer_container>::type pointer_iterator;
 
284
#else
 
285
    typedef typename pointer_container::iterator pointer_iterator;
 
286
#endif
 
287
 
 
288
#if defined (BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
 
289
    // Proxies need mutable access, and can't be friends with MSVC6
 
290
  public:
 
291
#endif
 
292
    Container &raw_container();
 
293
 
 
294
  private:
 
295
    void adjust_proxies (pointer_iterator, pointer_iterator, difference_type);
 
296
    void write_proxies (size_type, size_type);
 
297
    bool clear_proxy (pointer_impl &);         // detach and do not reset
 
298
    void clear_proxies (size_type, size_type); // detach and do not reset
 
299
    void claim_all_proxies (); // Makes all proxies point at this object
 
300
 
 
301
  private:
 
302
    held_type m_held_obj;
 
303
    pointer_container m_proxies;
 
304
  };
 
305
 
 
306
  template<class Container, class Holder, class Generator>
 
307
  container_proxy<Container, Holder, Generator>
 
308
  ::container_proxy ()
 
309
    : m_held_obj (Holder::create()),
 
310
    m_proxies ()
 
311
  {
 
312
    // Container is empty - no further processing
 
313
  }
 
314
 
 
315
  template<class Container, class Holder, class Generator>
 
316
  container_proxy<Container, Holder, Generator>
 
317
  ::container_proxy (held_type const &held)
 
318
    : m_held_obj (Holder::copy (held)),
 
319
    m_proxies (size())
 
320
  {
 
321
    write_proxies (0, size());
 
322
  }
 
323
 
 
324
  template<class Container, class Holder, class Generator>
 
325
  container_proxy<Container, Holder, Generator>
 
326
  ::container_proxy (container_proxy const &copy)
 
327
    : m_held_obj (Holder::copy (copy.m_held_obj)),
 
328
    m_proxies (size())
 
329
  {
 
330
    write_proxies (0, size()); // Create our own proxies for the copied values
 
331
  }
 
332
 
 
333
  template<class Container, class Holder, class Generator>
 
334
  container_proxy<Container, Holder, Generator> &
 
335
  container_proxy<Container, Holder, Generator>
 
336
  ::operator= (container_proxy const &copy)
 
337
  {
 
338
    container_proxy<Container, Holder, Generator> temp (copy);
 
339
    // This could throw, but none of the remaining operations can
 
340
 
 
341
    Holder::swap (m_held_obj, temp.m_held_obj);
 
342
    std::swap (m_proxies, temp.m_proxies);
 
343
 
 
344
    claim_all_proxies ();
 
345
    temp.claim_all_proxies ();  // Prepare for detach
 
346
 
 
347
    return *this;
 
348
    // temp destruction detaches any proxies that used to belong to us
 
349
  }
 
350
 
 
351
  template<class Container, class Holder, class Generator>
 
352
  container_proxy<Container, Holder, Generator>
 
353
  ::~container_proxy ()
 
354
  {
 
355
    // Copy original values into any proxies being shared by external pointers
 
356
    clear_proxies (0, size());
 
357
    Holder::pre_destruction (m_held_obj);
 
358
  }
 
359
 
 
360
  template<class Container, class Holder, class Generator>
 
361
  Container &
 
362
  container_proxy<Container, Holder, Generator>
 
363
  ::raw_container ()
 
364
  {
 
365
    return Holder::get (m_held_obj);
 
366
  }
 
367
 
 
368
  template<class Container, class Holder, class Generator>
 
369
  Container const &
 
370
  container_proxy<Container, Holder, Generator>
 
371
  ::raw_container () const
 
372
  {
 
373
    return Holder::get (m_held_obj);
 
374
  }
 
375
 
 
376
  template<class Container, class Holder, class Generator>
 
377
  void container_proxy<Container, Holder, Generator>::reserve (size_type size)
 
378
  {
 
379
    raw_container().reserve (size);
 
380
    m_proxies.reserve (size);
 
381
  }
 
382
 
 
383
  template<class Container, class Holder, class Generator>
 
384
  BOOST_DEDUCED_TYPENAME container_proxy<Container, Holder, Generator>::reference
 
385
  container_proxy<Container, Holder, Generator>
 
386
  ::at (size_type index)
 
387
  {
 
388
    pointer_impl const &ptr = m_proxies.BOOST_PYTHON_INDEXING_AT (index);
 
389
    assert (ptr->owner() == this);
 
390
    assert (ptr->index() == index);
 
391
    return reference (ptr);
 
392
  }
 
393
 
 
394
  template<class Container, class Holder, class Generator>
 
395
  BOOST_DEDUCED_TYPENAME container_proxy<Container, Holder, Generator>::const_reference
 
396
  container_proxy<Container, Holder, Generator>
 
397
  ::at (size_type index) const
 
398
  {
 
399
    pointer_impl const &ptr = m_proxies.BOOST_PYTHON_INDEXING_AT (index);
 
400
    assert (ptr->owner() == this);
 
401
    assert (ptr->index() == index);
 
402
    return const_reference (ptr);
 
403
  }
 
404
 
 
405
  template<class Container, class Holder, class Generator>
 
406
  void
 
407
  container_proxy<Container, Holder, Generator>
 
408
  ::replace (size_type index, raw_value_type const &copy)
 
409
  {
 
410
    detach_proxy (index);
 
411
    raw_container().BOOST_PYTHON_INDEXING_AT (index) = copy;
 
412
    write_proxies (index, index + 1);
 
413
  }
 
414
 
 
415
  template<class Container, class Holder, class Generator>
 
416
  void
 
417
  container_proxy<Container, Holder, Generator>
 
418
  ::swap_elements (size_type index1, size_type index2)
 
419
  {
 
420
    pointer_impl &ptr1 = m_proxies[index1];
 
421
    pointer_impl &ptr2 = m_proxies[index2];
 
422
 
 
423
    assert (ptr1->owner() == this);
 
424
    assert (ptr2->owner() == this);
 
425
    assert (ptr1->index() == index1);
 
426
    assert (ptr2->index() == index2);
 
427
 
 
428
    // Swap produces the diagrammed transformation. Any external
 
429
    // pointers that refer to proxy1 or proxy2 will end up still
 
430
    // pointing to their original (now relocated) values.
 
431
    //
 
432
    // .. ptr1 .. ptr2 ..     .. ptr1 .. ptr2  ..  (m_proxies)
 
433
    //      |      |                 \  /
 
434
    //      |      |                  \/
 
435
    //      |      |                  /\.
 
436
    //      V      V                 /  \.
 
437
    //   proxy1  proxy2  -->    proxy1  proxy2
 
438
    //      |      |                 \  /
 
439
    //      |      |                  \/
 
440
    //      |      |                  /\.
 
441
    //      V      V                 /  \.
 
442
    //  .. v1 ... v2 ..         .. v2 .. v1 ..  (raw_container)
 
443
 
 
444
    std::swap (ptr1->m_index, ptr2->m_index);
 
445
    std::swap (ptr1, ptr2);
 
446
    std::swap (raw_container()[index1], raw_container()[index2]);
 
447
 
 
448
    assert (m_proxies[index1]->index() == index1);
 
449
    assert (m_proxies[index2]->index() == index2);
 
450
  }
 
451
 
 
452
  template<class Container, class Holder, class Generator>
 
453
  BOOST_DEDUCED_TYPENAME container_proxy<Container, Holder, Generator>::iterator
 
454
  container_proxy<Container, Holder, Generator>::erase (iterator iter)
 
455
  {
 
456
    return erase (iter, iter + 1);
 
457
  }
 
458
 
 
459
  template<class Container, class Holder, class Generator>
 
460
  BOOST_DEDUCED_TYPENAME container_proxy<Container, Holder, Generator>::iterator
 
461
  container_proxy<Container, Holder, Generator>::erase(
 
462
      iterator from, iterator to)
 
463
  {
 
464
    assert (from.ptr == this);
 
465
    assert (to.ptr == this);
 
466
 
 
467
    // Detach and remove the proxies for the about-to-be-erased elements
 
468
    prepare_erase (from.index, to.index);
 
469
 
 
470
    // Erase the elements from the real container
 
471
    raw_iterator result
 
472
      = raw_container().erase(
 
473
          raw_container().begin() + from.index,
 
474
          raw_container().begin() + to.index);
 
475
 
 
476
    return iterator (this, result);
 
477
  }
 
478
 
 
479
  template<class Container, class Holder, class Generator>
 
480
  BOOST_DEDUCED_TYPENAME container_proxy<Container, Holder, Generator>::iterator
 
481
  container_proxy<Container, Holder, Generator>::insert(
 
482
      iterator iter, raw_value_type const &copy)
 
483
  {
 
484
    // Use the iterator-based version by treating the value as an
 
485
    // array of size one (see section 5.7/4 of the C++98 standard)
 
486
    insert (iter, &copy, (&copy) + 1, std::random_access_iterator_tag());
 
487
 
 
488
    return iter;
 
489
  }
 
490
 
 
491
  template<class Container, class Holder, class Generator>
 
492
  bool container_proxy<Container, Holder, Generator>::clear_proxy(
 
493
      pointer_impl &ptr)
 
494
  {
 
495
    // Warning - this can break the class invariant. Use only when the
 
496
    // pointer is about to be overwritten or removed from m_proxies
 
497
 
 
498
    assert (ptr->owner() == this);
 
499
 
 
500
    if (!ptr.unique())
 
501
      {
 
502
        ptr->detach (); // Cause proxy to copy element value
 
503
        return true;
 
504
      }
 
505
 
 
506
    else
 
507
      {
 
508
        // If the pointer isn't shared, don't bother causing a copy of
 
509
        // the container element, since the proxy is about to be
 
510
        // deleted or reused.
 
511
        return false;
 
512
      }
 
513
  }
 
514
 
 
515
  template<class Container, class Holder, class Generator>
 
516
  void container_proxy<Container, Holder, Generator>::clear_proxies(
 
517
      size_type from_index, size_type to_index)
 
518
  {
 
519
    while (from_index != to_index)
 
520
      {
 
521
        clear_proxy (m_proxies[from_index]);
 
522
        ++from_index;
 
523
      }
 
524
  }
 
525
 
 
526
  template<class Container, class Holder, class Generator>
 
527
  void container_proxy<Container, Holder, Generator>
 
528
  ::detach_proxy (size_type index)
 
529
  {
 
530
    pointer_impl &ptr = m_proxies[index];
 
531
 
 
532
    assert (ptr->index() == index);
 
533
 
 
534
    if (clear_proxy (ptr))
 
535
      {
 
536
        // To maintain class invariant
 
537
        ptr.reset (new shared_proxy (this, index));
 
538
      }
 
539
  }
 
540
 
 
541
  template<class Container, class Holder, class Generator>
 
542
  void container_proxy<Container, Holder, Generator>::detach_proxies(
 
543
      size_type from_index, size_type to_index)
 
544
  {
 
545
    while (from_index != to_index)
 
546
      {
 
547
        detach_proxy (from_index);
 
548
        ++from_index;
 
549
      }
 
550
  }
 
551
 
 
552
  template<class Container, class Holder, class Generator>
 
553
  void container_proxy<Container, Holder, Generator>
 
554
  ::prepare_erase (size_type from_index, size_type to_index)
 
555
  {
 
556
    difference_type deleting = to_index - from_index;
 
557
    pointer_iterator erase_begin = m_proxies.begin() + from_index;
 
558
    pointer_iterator erase_end = m_proxies.begin() + to_index;
 
559
 
 
560
    // Adjust the indexes of any trailing proxies
 
561
    adjust_proxies (erase_end, m_proxies.end(), -deleting);
 
562
 
 
563
    // Detach any proxies without updating our pointers to them
 
564
    clear_proxies (from_index, to_index);
 
565
 
 
566
    // Remove the pointers
 
567
    m_proxies.erase (erase_begin, erase_end);
 
568
  }
 
569
 
 
570
  template<class Container, class Holder, class Generator>
 
571
  void container_proxy<Container, Holder, Generator>::notify_insertion(
 
572
      size_type from_index, size_type to_index)
 
573
  {
 
574
    size_type count = to_index - from_index;
 
575
 
 
576
    m_proxies.insert(
 
577
        m_proxies.begin() + from_index, count, pointer_impl());
 
578
 
 
579
    try
 
580
      {
 
581
        write_proxies (from_index, to_index); // Could throw
 
582
      }
 
583
 
 
584
    catch (...)
 
585
      {
 
586
        m_proxies.erase(
 
587
            m_proxies.begin() + from_index,
 
588
            m_proxies.begin() + to_index);
 
589
 
 
590
        throw;
 
591
      }
 
592
 
 
593
    // Adjust any proxies after the inserted elements (nothrow)
 
594
    adjust_proxies(
 
595
        m_proxies.begin() + to_index,
 
596
        m_proxies.end(),
 
597
        static_cast<difference_type> (count));
 
598
  }
 
599
 
 
600
  template<class Container, class Holder, class Generator>
 
601
  void container_proxy<Container, Holder, Generator>::adjust_proxies(
 
602
      pointer_iterator from,
 
603
      pointer_iterator to,
 
604
      difference_type offset)
 
605
  {
 
606
    while (from != to)
 
607
      {
 
608
        (*from)->m_index += offset;
 
609
        ++from;
 
610
      }
 
611
  }
 
612
 
 
613
  template<class Container, class Holder, class Generator>
 
614
  void container_proxy<Container, Holder, Generator>::write_proxies(
 
615
      size_type from, size_type to)
 
616
  {
 
617
    // (over)write proxy pointers in the given range. Re-uses existing
 
618
    // shared_proxy objects where possible. Does not call detach_proxy
 
619
    // since it is assumed that the original values could have already
 
620
    // been modified and copying them now would be wrong.
 
621
 
 
622
    while (from != to)
 
623
      {
 
624
        pointer_impl &ptr = m_proxies[from];
 
625
 
 
626
        if ((ptr.get() == 0) || (!ptr.unique()))
 
627
          {
 
628
            // Either no proxy yet allocated here, or there is one
 
629
            // but it is being shared by an external pointer.
 
630
            ptr.reset (new shared_proxy (this, from));
 
631
          }
 
632
 
 
633
        else
 
634
          {
 
635
            // Re-use the existing object since we have the only pointer to it
 
636
            assert (ptr->owner() == this);
 
637
            ptr->m_index = from;
 
638
          }
 
639
 
 
640
        ++from;
 
641
      }
 
642
  }
 
643
 
 
644
  template<class Container, class Holder, class Generator>
 
645
  void container_proxy<Container, Holder, Generator>::claim_all_proxies ()
 
646
  {
 
647
    for (pointer_iterator iter = m_proxies.begin();
 
648
         iter != m_proxies.end();
 
649
         ++iter)
 
650
      {
 
651
        (*iter)->m_owner_ptr = this;
 
652
      }
 
653
  }
 
654
 
 
655
  template<class Container, class Holder, class Generator>
 
656
  bool container_proxy<Container, Holder, Generator>::is_valid () const
 
657
  {
 
658
    bool ok = size() == m_proxies.size(); // Sizes must match
 
659
 
 
660
    for (size_type count = 0; ok && (count < size()); ++count)
 
661
      {
 
662
        pointer_impl const &ptr = m_proxies[count];
 
663
 
 
664
        ok = ptr.get() && (ptr->owner() == this) && (ptr->index() == count)
 
665
          && !ptr->m_element_ptr.get();
 
666
      }
 
667
 
 
668
    return ok;
 
669
  }
 
670
 
 
671
  /////////////////////////////////////////////////////////////////////////
 
672
  // ContainerTraits implementation for container_proxy instances
 
673
  /////////////////////////////////////////////////////////////////////////
 
674
 
 
675
  template<typename Container>
 
676
  struct container_proxy_traits : random_access_sequence_traits<Container>
 
677
  {
 
678
    typedef Container container;
 
679
    typedef typename container::raw_value_type value_type; // insert, ...
 
680
    typedef typename container::raw_value_type key_type;   // find, count, ...
 
681
    typedef typename container::reference reference;  // return values
 
682
 
 
683
    typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <value_type>::param_type
 
684
        value_param;
 
685
    typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <key_type>::param_type
 
686
        key_param;
 
687
 
 
688
#if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
 
689
    // value_traits for the reference type (i.e. our element_proxy
 
690
    // instance) supplies a custom visit_container_class. Compilers
 
691
    // without partial specialization need help here.
 
692
 
 
693
    typedef element_proxy_traits<Container> value_traits_type;
 
694
 
 
695
    // Hide base class visit_container_class, which would call the
 
696
    // unspecialized value_traits version
 
697
    template<typename PythonClass, typename Policy>
 
698
    static void visit_container_class(
 
699
        PythonClass &pyClass, Policy const &policy)
 
700
    {
 
701
      value_traits_type::visit_container_class (pyClass, policy);
 
702
    }
 
703
#endif
 
704
  };
 
705
 
 
706
#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
 
707
  namespace detail {
 
708
    ///////////////////////////////////////////////////////////////////////
 
709
    // algorithms support for container_proxy instances
 
710
    ///////////////////////////////////////////////////////////////////////
 
711
 
 
712
    template <typename RawContainer, typename Holder, typename Generator>
 
713
    class algorithms_selector<container_proxy<RawContainer, Holder, Generator> >
 
714
    {
 
715
      typedef container_proxy<RawContainer, Holder, Generator> Container;
 
716
 
 
717
      typedef container_proxy_traits<Container>       mutable_traits;
 
718
      typedef container_proxy_traits<Container const> const_traits;
 
719
 
 
720
    public:
 
721
      typedef default_algorithms<mutable_traits> mutable_algorithms;
 
722
      typedef default_algorithms<const_traits>   const_algorithms;
 
723
    };
 
724
  }
 
725
#endif
 
726
  template<
 
727
      class Container,
 
728
      method_set_type MethodMask = all_methods,
 
729
      class Traits = container_proxy_traits<Container>
 
730
  >
 
731
  struct container_proxy_suite
 
732
    : container_suite<Container, MethodMask, default_algorithms<Traits> >
 
733
  {
 
734
  };
 
735
 
 
736
} } }
 
737
 
 
738
#endif // BOOST_PYTHON_INDEXING_CONTAINER_PROXY_HPP