~ubuntu-branches/ubuntu/warty/aqsis/warty

« back to all changes in this revision

Viewing changes to boost/boost/multi_array/iterator_adaptors.hpp

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2004-08-24 07:25:04 UTC
  • Revision ID: james.westby@ubuntu.com-20040824072504-zf993vnevvisdsvb
Tags: upstream-0.9.1
ImportĀ upstreamĀ versionĀ 0.9.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// (C) Copyright David Abrahams 2000. Permission to copy, use,
 
2
// modify, sell and distribute this software is granted provided this
 
3
// copyright notice appears in all copies. This software is provided
 
4
// "as is" without express or implied warranty, and with no claim as
 
5
// to its suitability for any purpose.
 
6
//
 
7
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
 
8
// sell and distribute this software is granted provided this
 
9
// copyright notice appears in all copies. This software is provided
 
10
// "as is" without express or implied warranty, and with no claim as
 
11
// to its suitability for any purpose.
 
12
//
 
13
 
 
14
// Thes code is modified from its original form to meet the needs of
 
15
// Boost.MultiArray.
 
16
 
 
17
// Revision History:
 
18
 
 
19
// 27 Mar 2002  Ronald Garcia
 
20
//      Forked from the main tree iterator adaptors. Necessary to
 
21
//      allow iterator::operator->*() to work with multi_array iterators.
 
22
// 01 Feb 2002   Jeremy Siek
 
23
//      Added more comments in default_iterator_policies.
 
24
// 08 Jan 2001   David Abrahams
 
25
//      Moved concept checks into a separate class, which makes MSVC
 
26
//      better at dealing with them.
 
27
// 07 Jan 2001   David Abrahams
 
28
//      Choose proxy for operator->() only if the reference type is not a reference.
 
29
//      Updated workarounds for __MWERKS__ == 0x2406
 
30
// 20 Dec 2001   David Abrahams
 
31
//      Adjusted is_convertible workarounds for __MWERKS__ == 0x2406
 
32
// 03 Nov 2001   Jeremy Siek
 
33
//      Changed the named template parameter interface and internal.
 
34
// 04 Oct 2001   Jeremy Siek
 
35
//      Changed projection_iterator to not rely on the default reference,
 
36
//      working around a limitation of detail::iterator_traits.
 
37
// 04 Oct 2001   David Abrahams
 
38
//      Applied indirect_iterator patch from George A. Heintzelman <georgeh@aya.yale.edu>
 
39
//      Changed name of "bind" to "select" to avoid problems with MSVC.
 
40
// 26 Sep 2001   David Abrahams
 
41
//      Added borland bug fix
 
42
// 08 Mar 2001   Jeremy Siek
 
43
//      Added support for optional named template parameters.
 
44
// 19 Feb 2001   David Abrahams
 
45
//      Rolled back reverse_iterator_pair_generator again, as it doesn't
 
46
//      save typing on a conforming compiler.
 
47
// 18 Feb 2001   David Abrahams
 
48
//      Reinstated reverse_iterator_pair_generator
 
49
// 16 Feb 2001   David Abrahams
 
50
//      Add an implicit conversion operator to operator_arrow_proxy
 
51
//      as CW and BCC workarounds.
 
52
// 11 Feb 2001   David Abrahams
 
53
//      Switch to use of BOOST_STATIC_CONSTANT where possible
 
54
// 11 Feb 2001   Jeremy Siek
 
55
//      Removed workaround for older MIPSpro compiler. The workaround
 
56
//        was preventing the proper functionality of the underlying
 
57
//        iterator being carried forward into the iterator adaptor.
 
58
//        Also added is_bidirectional enum to avoid EDG compiler error.
 
59
// 11 Feb 2001   David Abrahams
 
60
//      Borland fixes up the wazoo. It finally works!
 
61
// 10 Feb 2001   David Abrahams
 
62
//      Removed traits argument from iterator_adaptor<> and switched to
 
63
//        explicit trait specification for maximum ease-of-use.
 
64
//      Added comments to detail::iterator_defaults<>
 
65
//      Began using detail::iterator_defaults<> unconditionally for code clarity
 
66
//      Changed uses of `Iterator' to `Base' where non-iterators can be used.
 
67
//
 
68
// 10 Feb 2001   David Abrahams
 
69
//      Rolled in supposed Borland fixes from John Maddock, but not seeing any
 
70
//        improvement yet
 
71
//      Changed argument order to indirect_ generator, for convenience in the
 
72
//        case of input iterators (where Reference must be a value type).
 
73
//      Removed derivation of filter_iterator_policies from
 
74
//        default_iterator_policies, since the iterator category is likely to be
 
75
//        reduced (we don't want to allow illegal operations like decrement).
 
76
//      Support for a simpler filter iterator interface.
 
77
//
 
78
// 09 Feb 2001   David Abrahams
 
79
//      Improved interface to indirect_ and reverse_ iterators
 
80
//      Rolled back Jeremy's new constructor for now; it was causing
 
81
//        problems with counting_iterator_test
 
82
//      Attempted fix for Borland
 
83
//
 
84
// 09 Feb 2001   Jeremy Siek
 
85
//      Added iterator constructor to allow const adaptor
 
86
//        from non-const adaptee.
 
87
//      Changed make_xxx to pass iterators by-value to
 
88
//        get arrays converted to pointers.
 
89
//      Removed InnerIterator template parameter from
 
90
//        indirect_iterator_generator.
 
91
//      Rearranged parameters for make_filter_iterator
 
92
//
 
93
// 07 Feb 2001   Jeremy Siek
 
94
//      Removed some const iterator adaptor generators.
 
95
//      Added make_xxx_iterator() helper functions for remaining
 
96
//        iterator adaptors.
 
97
//      Removed some traits template parameters where they
 
98
//        where no longer needed thanks to detail::iterator_traits.
 
99
//      Moved some of the compile-time logic into enums for
 
100
//      EDG compatibility.
 
101
//
 
102
// 07 Feb 2001  David Abrahams
 
103
//      Removed iterator_adaptor_pair_generator and
 
104
//        reverse_iterator_pair_generator (more such culling to come)
 
105
//      Improved comments
 
106
//      Changed all uses of std::iterator_traits as default arguments
 
107
//        to boost::detail::iterator_traits for improved utility in
 
108
//        non-generic contexts
 
109
//      Fixed naming convention of non-template parameter names
 
110
//
 
111
// 06 Feb 2001   David Abrahams
 
112
//      Produce operator-> proxy objects for InputIterators
 
113
//      Added static assertions to do some basic concept checks
 
114
//      Renamed single-type generators -> xxx_generator
 
115
//      Renamed const/nonconst iterator generators -> xxx_pair_generator
 
116
//      Added make_transform_iterator(iter, function)
 
117
//      The existence of boost::detail::iterator_traits allowed many
 
118
//        template arguments to be defaulted. Some arguments had to be
 
119
//        moved to accomplish it.
 
120
//
 
121
// 04 Feb 2001  MWERKS bug workaround, concept checking for proper
 
122
//              reference types (David Abrahams)
 
123
 
 
124
#ifndef BOOST_ITERATOR_ADAPTOR_RG032702_HPP_
 
125
# define BOOST_ITERATOR_ADAPTOR_RG032702_HPP_
 
126
 
 
127
# include <boost/iterator.hpp>
 
128
# include <boost/utility.hpp>
 
129
# include <boost/compressed_pair.hpp>
 
130
# include <boost/concept_check.hpp>
 
131
# include <boost/type.hpp>
 
132
# include <boost/static_assert.hpp>
 
133
# include <boost/type_traits.hpp>
 
134
# include <boost/detail/iterator.hpp>
 
135
# include <boost/detail/select_type.hpp>
 
136
 
 
137
// I was having some problems with VC6. I couldn't tell whether our hack for
 
138
// stock GCC was causing problems so I needed an easy way to turn it on and
 
139
// off. Now we can test the hack with various compilers and still have an
 
140
// "out" if it doesn't work. -dwa 7/31/00
 
141
# if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 && !defined(__STL_USE_NAMESPACES)
 
142
#  define BOOST_RELOPS_AMBIGUITY_BUG 1
 
143
# endif
 
144
 
 
145
namespace boost {
 
146
namespace detail {
 
147
namespace multi_array {
 
148
 
 
149
//============================================================================
 
150
// Default policies for iterator adaptors. You can use this as a base
 
151
// class if you want to customize particular policies.
 
152
struct default_iterator_policies
 
153
{
 
154
    // Some of the member functions were defined static, but Borland
 
155
    // got confused and thought they were non-const. Also, Sun C++
 
156
    // does not like static function templates. 
 
157
    //
 
158
    // The reason some members were defined static is because there is
 
159
    // not state (data members) needed by those members of the
 
160
    // default_iterator_policies class. If your policies class member
 
161
    // functions need to access state stored in the policies object,
 
162
    // then the member functions should not be static (they can't be).
 
163
 
 
164
    template <class Base>
 
165
    void initialize(Base&)
 
166
        { }
 
167
 
 
168
    template <class IteratorAdaptor>
 
169
    typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const
 
170
        { return *x.base(); }
 
171
 
 
172
    template <class IteratorAdaptor>
 
173
    void increment(IteratorAdaptor& x)
 
174
        { ++x.base(); }
 
175
 
 
176
    template <class IteratorAdaptor>
 
177
    void decrement(IteratorAdaptor& x)
 
178
        { --x.base(); }
 
179
 
 
180
    template <class IteratorAdaptor, class DifferenceType>
 
181
    void advance(IteratorAdaptor& x, DifferenceType n)
 
182
        { x.base() += n; }
 
183
 
 
184
    template <class IteratorAdaptor1, class IteratorAdaptor2>
 
185
    typename IteratorAdaptor1::difference_type
 
186
    distance(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
 
187
        { return y.base() - x.base(); }
 
188
 
 
189
    template <class IteratorAdaptor1, class IteratorAdaptor2>
 
190
    bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
 
191
        { return x.base() == y.base(); }
 
192
};
 
193
 
 
194
// putting the comparisons in a base class avoids the g++
 
195
// ambiguous overload bug due to the relops operators
 
196
 
 
197
#ifdef BOOST_RELOPS_AMBIGUITY_BUG
 
198
template <class Derived, class Base>
 
199
struct iterator_comparisons : Base { };
 
200
 
 
201
template <class D1, class D2, class Base1, class Base2>
 
202
inline bool operator==(const iterator_comparisons<D1,Base1>& xb,
 
203
                       const iterator_comparisons<D2,Base2>& yb)
 
204
{
 
205
        const D1& x = static_cast<const D1&>(xb);
 
206
    const D2& y = static_cast<const D2&>(yb);
 
207
    return x.policies().equal(x, y);
 
208
}
 
209
 
 
210
template <class D1, class D2, class Base1, class Base2>
 
211
inline bool operator!=(const iterator_comparisons<D1,Base1>& xb,
 
212
                       const iterator_comparisons<D2,Base2>& yb)
 
213
{
 
214
    const D1& x = static_cast<const D1&>(xb);
 
215
    const D2& y = static_cast<const D2&>(yb);
 
216
    return !x.policies().equal(x, y);
 
217
}
 
218
 
 
219
template <class D1, class D2, class Base1, class Base2>
 
220
inline bool operator<(const iterator_comparisons<D1,Base1>& xb,
 
221
                      const iterator_comparisons<D2,Base2>& yb)
 
222
{
 
223
    const D1& x = static_cast<const D1&>(xb);
 
224
    const D2& y = static_cast<const D2&>(yb);
 
225
    return x.policies().distance(y, x) < 0;
 
226
}
 
227
 
 
228
template <class D1, class D2, class Base1, class Base2>
 
229
inline bool operator>(const iterator_comparisons<D1,Base1>& xb,
 
230
                      const iterator_comparisons<D2,Base2>& yb)
 
231
{
 
232
    const D1& x = static_cast<const D1&>(xb);
 
233
    const D2& y = static_cast<const D2&>(yb);
 
234
    return x.policies().distance(y, x) > 0;
 
235
}
 
236
 
 
237
template <class D1, class D2, class Base1, class Base2>
 
238
inline bool operator>=(const iterator_comparisons<D1,Base1>& xb,
 
239
                       const iterator_comparisons<D2,Base2>& yb)
 
240
{
 
241
    const D1& x = static_cast<const D1&>(xb);
 
242
    const D2& y = static_cast<const D2&>(yb);
 
243
    return x.policies().distance(y, x) >= 0;
 
244
}
 
245
 
 
246
template <class D1, class D2, class Base1, class Base2>
 
247
inline bool operator<=(const iterator_comparisons<D1,Base1>& xb,
 
248
                       const iterator_comparisons<D2,Base2>& yb)
 
249
{
 
250
    const D1& x = static_cast<const D1&>(xb);
 
251
    const D2& y = static_cast<const D2&>(yb);
 
252
    return x.policies().distance(y, x) <= 0;
 
253
}
 
254
#endif
 
255
 
 
256
namespace detail {
 
257
 
 
258
  // operator->() needs special support for input iterators to strictly meet the
 
259
  // standard's requirements. If *i is not a reference type, we must still
 
260
  // produce a (constant) lvalue to which a pointer can be formed. We do that by
 
261
  // returning an instantiation of this special proxy class template.
 
262
 
 
263
  template <class T>
 
264
  struct operator_arrow_proxy
 
265
  {
 
266
      operator_arrow_proxy(const T& x) : m_value(x) {}
 
267
    // RG removed const below
 
268
      T* operator->() const { return &m_value; }
 
269
      // This function is needed for MWCW and BCC, which won't call operator->
 
270
      // again automatically per 13.3.1.2 para 8
 
271
 
 
272
    // RG - removed const below
 
273
      operator T*() const { return &m_value; }
 
274
      mutable T m_value;
 
275
  };
 
276
 
 
277
  template <class Iter>
 
278
  inline operator_arrow_proxy<typename Iter::reference>
 
279
  operator_arrow(const Iter& i, std::input_iterator_tag) {
 
280
    // RG - THIS is the change I needed to make!
 
281
    // My input iterators need to return proxy references rather than values
 
282
    typedef typename Iter::reference value_t; // VC++ needs this typedef
 
283
    return operator_arrow_proxy<value_t>(*i);
 
284
  }
 
285
 
 
286
  template <class Iter>
 
287
  inline typename Iter::pointer
 
288
  operator_arrow(const Iter& i, std::forward_iterator_tag) {
 
289
    return &(*i);
 
290
  }
 
291
 
 
292
  template <class Value, class Reference, class Pointer>
 
293
  struct operator_arrow_result_generator
 
294
  {
 
295
    //RG - another important change!
 
296
      typedef operator_arrow_proxy<Reference> proxy;
 
297
      // Borland chokes unless it's an actual enum (!)
 
298
      enum { use_proxy = !boost::is_reference<Reference>::value };
 
299
 
 
300
      typedef typename boost::detail::if_true<(use_proxy)>::template
 
301
      then<
 
302
        proxy,
 
303
   // else
 
304
        Pointer
 
305
      >::type type;
 
306
  };
 
307
 
 
308
# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_STD_ITERATOR_TRAITS)
 
309
 
 
310
 
 
311
   // Select default pointer and reference types for adapted non-pointer
 
312
   // iterators based on the iterator and the value_type. Poor man's partial
 
313
   // specialization is in use here.
 
314
   template <bool is_pointer>
 
315
   struct iterator_defaults_select
 
316
   {
 
317
       template <class Iterator,class Value>
 
318
       struct traits
 
319
       {
 
320
           // The assumption is that iterator_traits can deduce these types
 
321
           // properly as long as the iterator is not a pointer.
 
322
           typedef typename boost::detail::iterator_traits<Iterator>::pointer pointer;
 
323
           typedef typename boost::detail::iterator_traits<Iterator>::reference reference;
 
324
       };
 
325
   };
 
326
 
 
327
   // Select default pointer and reference types for adapted pointer iterators
 
328
   // given a (possibly-const) value_type.
 
329
   template <>
 
330
   struct iterator_defaults_select<true>
 
331
   {
 
332
       template <class Iterator,class Value>
 
333
       struct traits
 
334
       {
 
335
           typedef Value* pointer;
 
336
           typedef Value& reference;
 
337
       };
 
338
   };
 
339
 
 
340
   // Consolidate selection of the default pointer and reference type
 
341
   template <class Iterator,class Value>
 
342
   struct iterator_defaults
 
343
   {
 
344
       BOOST_STATIC_CONSTANT(bool, is_ptr = boost::is_pointer<Iterator>::value);
 
345
 
 
346
       typedef typename iterator_defaults_select<is_ptr>::template traits<Iterator,Value> traits;
 
347
       typedef typename traits::pointer pointer;
 
348
       typedef typename traits::reference reference;
 
349
   };
 
350
# else
 
351
   template <class Iterator,class Value>
 
352
   struct iterator_defaults : iterator_traits<Iterator>
 
353
   {
 
354
       // Trying to factor the common is_same expression into an enum or a
 
355
       // static bool constant confused Borland.
 
356
       typedef typename if_true<(
 
357
               ::boost::is_same<Value,typename iterator_traits<Iterator>::value_type>::value
 
358
           )>::template then<
 
359
                typename iterator_traits<Iterator>::pointer,
 
360
                Value*
 
361
       >::type pointer;
 
362
 
 
363
       typedef typename if_true<(
 
364
               ::boost::is_same<Value,typename iterator_traits<Iterator>::value_type>::value
 
365
           )>::template then<
 
366
                typename iterator_traits<Iterator>::reference,
 
367
                Value&
 
368
       >::type reference;
 
369
 
 
370
   };
 
371
# endif
 
372
 
 
373
  //===========================================================================
 
374
  // Specify the defaults for iterator_adaptor's template parameters
 
375
 
 
376
  struct default_argument { };
 
377
  // This class template is a workaround for MSVC.
 
378
  struct dummy_default_gen {
 
379
    template <class Base, class Traits>
 
380
    struct select { typedef default_argument type; };
 
381
  };
 
382
  // This class template is a workaround for MSVC.
 
383
  template <class Gen> struct default_generator {
 
384
    typedef dummy_default_gen type;
 
385
  };
 
386
 
 
387
  struct default_value_type {
 
388
    template <class Base, class Traits>
 
389
    struct select {
 
390
      typedef typename boost::detail::iterator_traits<Base>::value_type type;
 
391
    };
 
392
  };
 
393
  template <> struct default_generator<default_value_type>
 
394
  { typedef default_value_type type; }; // VC++ workaround
 
395
 
 
396
  struct default_difference_type {
 
397
    template <class Base, class Traits>
 
398
    struct select {
 
399
      typedef typename boost::detail::iterator_traits<Base>::difference_type type;
 
400
    };
 
401
  };
 
402
  template <> struct default_generator<default_difference_type>
 
403
  { typedef default_difference_type type; }; // VC++ workaround
 
404
 
 
405
  struct default_iterator_category {
 
406
    template <class Base, class Traits>
 
407
    struct select {
 
408
      typedef typename boost::detail::iterator_traits<Base>::iterator_category type;
 
409
    };
 
410
  };
 
411
  template <> struct default_generator<default_iterator_category>
 
412
  { typedef default_iterator_category type; }; // VC++ workaround
 
413
 
 
414
  struct default_pointer {
 
415
    template <class Base, class Traits>
 
416
    struct select {
 
417
      typedef typename Traits::value_type Value;
 
418
      typedef typename boost::detail::multi_array::detail::iterator_defaults<Base,Value>::pointer
 
419
        type;
 
420
    };
 
421
  };
 
422
  template <> struct default_generator<default_pointer>
 
423
  { typedef default_pointer type; }; // VC++ workaround
 
424
 
 
425
  struct default_reference {
 
426
    template <class Base, class Traits>
 
427
    struct select {
 
428
      typedef typename Traits::value_type Value;
 
429
      typedef typename boost::detail::multi_array::detail::iterator_defaults<Base,Value>::reference
 
430
        type;
 
431
    };
 
432
  };
 
433
  template <> struct default_generator<default_reference>
 
434
  { typedef default_reference type; }; // VC++ workaround
 
435
 
 
436
} // namespace detail
 
437
 
 
438
 
 
439
  //===========================================================================
 
440
  // Support for named template parameters
 
441
 
 
442
struct named_template_param_base { };
 
443
 
 
444
namespace detail {
 
445
  struct value_type_tag { };
 
446
  struct reference_tag { };
 
447
  struct pointer_tag { };
 
448
  struct difference_type_tag { };
 
449
  struct iterator_category_tag { };
 
450
 
 
451
  // avoid using std::pair because A or B might be a reference type, and g++
 
452
  // complains about forming references to references inside std::pair
 
453
  template <class A, class B>
 
454
  struct cons_type {
 
455
    typedef A first_type;
 
456
    typedef B second_type;
 
457
  };
 
458
 
 
459
} // namespace detail
 
460
 
 
461
template <class Value> struct value_type_is : public named_template_param_base
 
462
{
 
463
  typedef detail::cons_type<detail::value_type_tag, Value> type;
 
464
};
 
465
template <class Reference> struct reference_is : public named_template_param_base
 
466
{
 
467
  typedef detail::cons_type<detail::reference_tag, Reference> type;
 
468
};
 
469
template <class Pointer> struct pointer_is : public named_template_param_base
 
470
{
 
471
  typedef detail::cons_type<detail::pointer_tag, Pointer> type;
 
472
};
 
473
template <class Difference> struct difference_type_is
 
474
  : public named_template_param_base
 
475
{
 
476
  typedef detail::cons_type<detail::difference_type_tag, Difference> type;
 
477
};
 
478
template <class IteratorCategory> struct iterator_category_is
 
479
  : public named_template_param_base
 
480
{
 
481
  typedef detail::cons_type<detail::iterator_category_tag, IteratorCategory> type;
 
482
};
 
483
 
 
484
namespace detail {
 
485
 
 
486
  struct end_of_list { };
 
487
 
 
488
  // Given an associative list, find the value with the matching key.
 
489
  // An associative list is a list of key-value pairs. The list is
 
490
  // built out of cons_type's and is terminated by end_of_list.
 
491
 
 
492
# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(__BORLANDC__)
 
493
  template <class AssocList, class Key>
 
494
  struct find_param;
 
495
 
 
496
  struct find_param_continue {
 
497
    template <class AssocList, class Key2> struct select {
 
498
      typedef typename AssocList::first_type Head;
 
499
      typedef typename Head::first_type Key1;
 
500
      typedef typename Head::second_type Value;
 
501
      typedef typename if_true<(is_same<Key1, Key2>::value)>::template
 
502
      then<Value,
 
503
        typename find_param<typename AssocList::second_type, Key2>::type
 
504
      >::type type;
 
505
    };
 
506
  };
 
507
  struct find_param_end {
 
508
    template <class AssocList, class Key>
 
509
    struct select { typedef detail::default_argument type; };
 
510
  };
 
511
  template <class AssocList> struct find_param_helper1
 
512
  { typedef find_param_continue type; };
 
513
  template <> struct find_param_helper1<end_of_list>
 
514
  { typedef find_param_end type; };
 
515
 
 
516
  template <class AssocList, class Key>
 
517
  struct find_param {
 
518
    typedef typename find_param_helper1<AssocList>::type select1;
 
519
    typedef typename select1::template select<AssocList, Key>::type type;
 
520
  };
 
521
# else
 
522
  template <class AssocList, class Key> struct find_param;
 
523
 
 
524
  template <class Key>
 
525
  struct find_param<end_of_list, Key> { typedef default_argument type; };
 
526
 
 
527
  // Found a matching Key, return the associated Value
 
528
  template <class Key, class Value, class Rest>
 
529
  struct find_param<detail::cons_type< detail::cons_type<Key, Value>, Rest>, Key> {
 
530
    typedef Value type;
 
531
  };
 
532
 
 
533
  // Non-matching keys, continue the search
 
534
  template <class Key1, class Value, class Rest, class Key2>
 
535
  struct find_param<detail::cons_type< detail::cons_type<Key1, Value>, Rest>, Key2> {
 
536
    typedef typename find_param<Rest, Key2>::type type;
 
537
  };
 
538
# endif
 
539
 
 
540
  struct make_named_arg {
 
541
    template <class Key, class Value>
 
542
    struct select { typedef typename Value::type type; };
 
543
  };
 
544
  struct make_key_value {
 
545
    template <class Key, class Value>
 
546
    struct select { typedef detail::cons_type<Key, Value> type; };
 
547
  };
 
548
 
 
549
  template <class Value>
 
550
  struct is_named_parameter
 
551
  {
 
552
      enum { value = is_convertible<Value, named_template_param_base>::value };
 
553
  };
 
554
 
 
555
# if defined(__MWERKS__) && __MWERKS__ <= 0x2406 // workaround for broken is_convertible implementation
 
556
  template <class T> struct is_named_parameter<value_type_is<T> > { enum { value = true }; };
 
557
  template <class T> struct is_named_parameter<reference_is<T> > { enum { value = true }; };
 
558
  template <class T> struct is_named_parameter<pointer_is<T> > { enum { value = true }; };
 
559
  template <class T> struct is_named_parameter<difference_type_is<T> > { enum { value = true }; };
 
560
  template <class T> struct is_named_parameter<iterator_category_is<T> > { enum { value = true }; };
 
561
# endif
 
562
 
 
563
  template <class Key, class Value>
 
564
  struct make_arg {
 
565
# ifdef __BORLANDC__
 
566
    // Borland C++ doesn't like the extra indirection of is_named_parameter
 
567
    typedef typename
 
568
      if_true<(is_convertible<Value,named_template_param_base>::value)>::
 
569
      template then<make_named_arg, make_key_value>::type Make;
 
570
# else
 
571
    enum { is_named = is_named_parameter<Value>::value };
 
572
    typedef typename if_true<(is_named)>::template
 
573
      then<make_named_arg, make_key_value>::type Make;
 
574
# endif
 
575
    typedef typename Make::template select<Key, Value>::type type;
 
576
  };
 
577
 
 
578
  // Mechanism for resolving the default argument for a template parameter.
 
579
 
 
580
  template <class T> struct is_default { typedef type_traits::no_type type; };
 
581
  template <> struct is_default<default_argument>
 
582
  { typedef type_traits::yes_type type; };
 
583
 
 
584
  struct choose_default {
 
585
    template <class Arg, class DefaultGen, class Base, class Traits>
 
586
    struct select {
 
587
      typedef typename default_generator<DefaultGen>::type Gen;
 
588
      typedef typename Gen::template select<Base,Traits>::type type;
 
589
    };
 
590
  };
 
591
  struct choose_arg {
 
592
    template <class Arg, class DefaultGen, class Base, class Traits>
 
593
    struct select {
 
594
      typedef Arg type;
 
595
    };
 
596
  };
 
597
 
 
598
  template <class UseDefault>
 
599
  struct choose_arg_or_default { typedef choose_arg type; };
 
600
  template <> struct choose_arg_or_default<type_traits::yes_type> {
 
601
    typedef choose_default type;
 
602
  };
 
603
 
 
604
  template <class Arg, class DefaultGen, class Base, class Traits>
 
605
  class resolve_default {
 
606
    typedef typename choose_arg_or_default<typename is_default<Arg>::type>::type
 
607
      Selector;
 
608
  public:
 
609
    typedef typename Selector
 
610
      ::template select<Arg, DefaultGen, Base, Traits>::type type;
 
611
  };
 
612
 
 
613
  template <class Base, class Value, class Reference, class Pointer,
 
614
            class Category, class Distance>
 
615
  class iterator_adaptor_traits_gen
 
616
  {
 
617
    // Form an associative list out of the template parameters
 
618
    // If the argument is a normal parameter (not named) then make_arg
 
619
    // creates a key-value pair. If the argument is a named parameter,
 
620
    // then make_arg extracts the key-value pair defined inside the
 
621
    // named parameter.
 
622
    typedef detail::cons_type< typename make_arg<value_type_tag, Value>::type,
 
623
      detail::cons_type<typename make_arg<reference_tag, Reference>::type,
 
624
      detail::cons_type<typename make_arg<pointer_tag, Pointer>::type,
 
625
      detail::cons_type<typename make_arg<iterator_category_tag, Category>::type,
 
626
      detail::cons_type<typename make_arg<difference_type_tag, Distance>::type,
 
627
                end_of_list> > > > > ArgList;
 
628
 
 
629
    // Search the list for particular parameters
 
630
    typedef typename find_param<ArgList, value_type_tag>::type Val;
 
631
    typedef typename find_param<ArgList, difference_type_tag>::type Diff;
 
632
    typedef typename find_param<ArgList, iterator_category_tag>::type Cat;
 
633
    typedef typename find_param<ArgList, pointer_tag>::type Ptr;
 
634
    typedef typename find_param<ArgList, reference_tag>::type Ref;
 
635
 
 
636
    typedef boost::iterator<Category, Value, Distance, Pointer, Reference>
 
637
      Traits0;
 
638
 
 
639
    // Compute the defaults if necessary
 
640
    typedef typename resolve_default<Val, default_value_type, Base, Traits0>::type
 
641
      value_type;
 
642
    // if getting default value type from iterator_traits, then it won't be const
 
643
    typedef typename resolve_default<Diff, default_difference_type, Base,
 
644
      Traits0>::type difference_type;
 
645
    typedef typename resolve_default<Cat, default_iterator_category, Base,
 
646
      Traits0>::type iterator_category;
 
647
 
 
648
    typedef boost::iterator<iterator_category, value_type, difference_type,
 
649
      Pointer, Reference> Traits1;
 
650
 
 
651
    // Compute the defaults for pointer and reference. This is done as a
 
652
    // separate step because the defaults for pointer and reference depend
 
653
    // on value_type.
 
654
    typedef typename resolve_default<Ptr, default_pointer, Base, Traits1>::type
 
655
      pointer;
 
656
    typedef typename resolve_default<Ref, default_reference, Base, Traits1>::type
 
657
      reference;
 
658
 
 
659
  public:
 
660
    typedef boost::iterator<iterator_category,
 
661
      typename remove_const<value_type>::type,
 
662
      difference_type, pointer, reference> type;
 
663
  };
 
664
 
 
665
  // This is really a partial concept check for iterators. Should it
 
666
  // be moved or done differently?
 
667
  template <class Category, class Value, class Difference, class Pointer, class Reference>
 
668
  struct validator
 
669
  {
 
670
      BOOST_STATIC_CONSTANT(
 
671
          bool, is_input_or_output_iter
 
672
          = (boost::is_convertible<Category*,std::input_iterator_tag*>::value
 
673
             | boost::is_convertible<Category*,std::output_iterator_tag*>::value));
 
674
 
 
675
      // Iterators should satisfy one of the known categories
 
676
      BOOST_STATIC_ASSERT(is_input_or_output_iter);
 
677
 
 
678
      // Iterators >= ForwardIterator must produce real references
 
679
      // as required by the C++ standard requirements in Table 74.
 
680
      BOOST_STATIC_CONSTANT(
 
681
          bool, forward_iter_with_real_reference
 
682
          = ((!boost::is_convertible<Category*,std::forward_iterator_tag*>::value)
 
683
             | boost::is_same<Reference,Value&>::value
 
684
             | boost::is_same<Reference,typename add_const<Value>::type&>::value));
 
685
 
 
686
      BOOST_STATIC_ASSERT(forward_iter_with_real_reference);
 
687
  };
 
688
} // namespace detail
 
689
 
 
690
 
 
691
 
 
692
// This macro definition is only temporary in this file
 
693
# if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
 
694
#  define BOOST_ARG_DEPENDENT_TYPENAME typename
 
695
# else
 
696
#  define BOOST_ARG_DEPENDENT_TYPENAME
 
697
# endif
 
698
 
 
699
//============================================================================
 
700
//iterator_adaptor - Adapts a generic piece of data as an iterator. Adaptation
 
701
//      is especially easy if the data being adapted is itself an iterator
 
702
//
 
703
//   Base - the base (usually iterator) type being wrapped.
 
704
//
 
705
//   Policies - a set of policies determining how the resulting iterator
 
706
//      works.
 
707
//
 
708
//   Value - if supplied, the value_type of the resulting iterator, unless
 
709
//      const. If const, a conforming compiler strips constness for the
 
710
//      value_type. If not supplied, iterator_traits<Base>::value_type is used
 
711
//
 
712
//   Reference - the reference type of the resulting iterator, and in
 
713
//      particular, the result type of operator*(). If not supplied but
 
714
//      Value is supplied, Value& is used. Otherwise
 
715
//      iterator_traits<Base>::reference is used.
 
716
//
 
717
//   Pointer - the pointer type of the resulting iterator, and in
 
718
//      particular, the result type of operator->(). If not
 
719
//      supplied but Value is supplied, Value* is used. Otherwise
 
720
//      iterator_traits<Base>::pointer is used.
 
721
//
 
722
//   Category - the iterator_category of the resulting iterator. If not
 
723
//      supplied, iterator_traits<Base>::iterator_category is used.
 
724
//
 
725
//   Distance - the difference_type of the resulting iterator. If not
 
726
//      supplied, iterator_traits<Base>::difference_type is used.
 
727
template <class Base, class Policies,
 
728
    class Value = ::boost::detail::multi_array::detail::default_argument,
 
729
    class Reference = ::boost::detail::multi_array::detail::default_argument,
 
730
    class Pointer = ::boost::detail::multi_array::detail::default_argument,
 
731
    class Category = ::boost::detail::multi_array::detail::default_argument,
 
732
    class Distance = ::boost::detail::multi_array::detail::default_argument
 
733
         >
 
734
struct iterator_adaptor :
 
735
#ifdef BOOST_RELOPS_AMBIGUITY_BUG
 
736
    iterator_comparisons<
 
737
          iterator_adaptor<Base,Policies,Value,Reference,Pointer,Category,Distance>,
 
738
    typename detail::iterator_adaptor_traits_gen<Base,Value,Reference,Pointer,Category, Distance>::type
 
739
 >
 
740
#else
 
741
    detail::iterator_adaptor_traits_gen<Base,Value,Reference,Pointer,Category,Distance>::type
 
742
#endif
 
743
{
 
744
    typedef iterator_adaptor<Base,Policies,Value,Reference,Pointer,Category,Distance> self;
 
745
 public:
 
746
    typedef detail::iterator_adaptor_traits_gen<Base,Value,Reference,Pointer,Category,Distance> TraitsGen;
 
747
    typedef typename TraitsGen::type Traits;
 
748
 
 
749
    typedef typename Traits::difference_type difference_type;
 
750
    typedef typename Traits::value_type value_type;
 
751
    typedef typename Traits::pointer pointer;
 
752
    typedef typename Traits::reference reference;
 
753
    typedef typename Traits::iterator_category iterator_category;
 
754
 
 
755
    typedef Base base_type;
 
756
    typedef Policies policies_type;
 
757
 
 
758
 private:
 
759
    typedef detail::validator<
 
760
        iterator_category,value_type,difference_type,pointer,reference
 
761
        > concept_check;
 
762
 
 
763
 public:
 
764
    iterator_adaptor()
 
765
    {
 
766
    }
 
767
 
 
768
    explicit
 
769
    iterator_adaptor(const Base& it, const Policies& p = Policies())
 
770
        : m_iter_p(it, p) {
 
771
        policies().initialize(base());
 
772
    }
 
773
 
 
774
    template <class Iter2, class Value2, class Pointer2, class Reference2>
 
775
    iterator_adaptor (
 
776
        const iterator_adaptor<Iter2,Policies,Value2,Reference2,Pointer2,Category,Distance>& src)
 
777
            : m_iter_p(src.base(), src.policies())
 
778
    {
 
779
        policies().initialize(base());
 
780
    }
 
781
 
 
782
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__BORLANDC__)
 
783
    // This is required to prevent a bug in how VC++ generates
 
784
    // the assignment operator for compressed_pair
 
785
    iterator_adaptor& operator= (const iterator_adaptor& x) {
 
786
        m_iter_p = x.m_iter_p;
 
787
        return *this;
 
788
    }
 
789
#endif
 
790
    reference operator*() const {
 
791
         return policies().dereference(*this);
 
792
    }
 
793
 
 
794
#ifdef BOOST_MSVC
 
795
# pragma warning(push)
 
796
# pragma warning( disable : 4284 )
 
797
#endif
 
798
 
 
799
    typename boost::detail::multi_array::detail::operator_arrow_result_generator<value_type,reference,pointer>::type
 
800
    operator->() const
 
801
        { return detail::operator_arrow(*this, iterator_category()); }
 
802
 
 
803
#ifdef BOOST_MSVC
 
804
# pragma warning(pop)
 
805
#endif
 
806
 
 
807
    value_type operator[](difference_type n) const
 
808
        { return *(*this + n); }
 
809
 
 
810
    self& operator++() {
 
811
#if !defined(__MWERKS__) || __MWERKS__ >= 0x2405
 
812
        policies().increment(*this);
 
813
#else
 
814
        // Odd bug, MWERKS couldn't  deduce the type for the member template
 
815
        // Workaround by explicitly specifying the type.
 
816
        policies().increment<self>(*this);
 
817
#endif
 
818
        return *this;
 
819
    }
 
820
 
 
821
    self operator++(int) { self tmp(*this); ++*this; return tmp; }
 
822
 
 
823
    self& operator--() {
 
824
#if !defined(__MWERKS__) || __MWERKS__ >= 0x2405
 
825
        policies().decrement(*this);
 
826
#else
 
827
        policies().decrement<self>(*this);
 
828
#endif
 
829
        return *this;
 
830
    }
 
831
 
 
832
    self operator--(int) { self tmp(*this); --*this; return tmp; }
 
833
 
 
834
    self& operator+=(difference_type n) {
 
835
        policies().advance(*this, n);
 
836
        return *this;
 
837
    }
 
838
 
 
839
    self& operator-=(difference_type n) {
 
840
        policies().advance(*this, -n);
 
841
        return *this;
 
842
    }
 
843
 
 
844
    base_type const& base() const { return m_iter_p.first(); }
 
845
 
 
846
    // Moved from global scope to avoid ambiguity with the operator-() which
 
847
    // subtracts iterators from one another.
 
848
    self operator-(difference_type x) const
 
849
        { self result(*this); return result -= x; }
 
850
private:
 
851
    compressed_pair<Base,Policies> m_iter_p;
 
852
 
 
853
public: // implementation details (too many compilers have trouble when these are private).
 
854
    base_type& base() { return m_iter_p.first(); }
 
855
    Policies& policies() { return m_iter_p.second(); }
 
856
    const Policies& policies() const { return m_iter_p.second(); }
 
857
};
 
858
 
 
859
template <class Base, class Policies, class Value, class Reference, class Pointer,
 
860
    class Category, class Distance1, class Distance2>
 
861
iterator_adaptor<Base,Policies,Value,Reference,Pointer,Category,Distance1>
 
862
operator+(
 
863
    iterator_adaptor<Base,Policies,Value,Reference,Pointer,Category,Distance1> p,
 
864
    Distance2 x)
 
865
{
 
866
    return p += x;
 
867
}
 
868
 
 
869
template <class Base, class Policies, class Value, class Reference, class Pointer,
 
870
    class Category, class Distance1, class Distance2>
 
871
iterator_adaptor<Base,Policies,Value,Reference,Pointer,Category,Distance1>
 
872
operator+(
 
873
    Distance2 x,
 
874
    iterator_adaptor<Base,Policies,Value,Reference,Pointer,Category,Distance1> p)
 
875
{
 
876
    return p += x;
 
877
}
 
878
 
 
879
template <class Iterator1, class Iterator2, class Policies, class Value1, class Value2,
 
880
    class Reference1, class Reference2, class Pointer1, class Pointer2, class Category,
 
881
    class Distance>
 
882
typename iterator_adaptor<Iterator1,Policies,Value1,Reference1,Pointer1,Category,Distance>::difference_type
 
883
operator-(
 
884
    const iterator_adaptor<Iterator1,Policies,Value1,Reference1,Pointer1,Category,Distance>& x,
 
885
    const iterator_adaptor<Iterator2,Policies,Value2,Reference2,Pointer2,Category,Distance>& y)
 
886
{
 
887
  typedef typename iterator_adaptor<Iterator1,Policies,Value1,Reference1,
 
888
    Pointer1,Category,Distance>::difference_type difference_type;
 
889
  return x.policies().distance(y, x);
 
890
}
 
891
 
 
892
#ifndef BOOST_RELOPS_AMBIGUITY_BUG
 
893
template <class Iterator1, class Iterator2, class Policies, class Value1, class Value2,
 
894
    class Reference1, class Reference2, class Pointer1, class Pointer2,
 
895
    class Category, class Distance>
 
896
inline bool
 
897
operator==(
 
898
    const iterator_adaptor<Iterator1,Policies,Value1,Reference1,Pointer1,Category,Distance>& x,
 
899
    const iterator_adaptor<Iterator2,Policies,Value2,Reference2,Pointer2,Category,Distance>& y)
 
900
{
 
901
    return x.policies().equal(x, y);
 
902
}
 
903
 
 
904
template <class Iterator1, class Iterator2, class Policies, class Value1, class Value2,
 
905
    class Reference1, class Reference2, class Pointer1, class Pointer2,
 
906
    class Category, class Distance>
 
907
inline bool
 
908
operator<(
 
909
    const iterator_adaptor<Iterator1,Policies,Value1,Reference1,Pointer1,Category,Distance>& x,
 
910
    const iterator_adaptor<Iterator2,Policies,Value2,Reference2,Pointer2,Category,Distance>& y)
 
911
{
 
912
    return x.policies().distance(y, x) < 0;
 
913
}
 
914
 
 
915
template <class Iterator1, class Iterator2, class Policies, class Value1, class Value2,
 
916
    class Reference1, class Reference2, class Pointer1, class Pointer2,
 
917
    class Category, class Distance>
 
918
inline bool
 
919
operator>(
 
920
    const iterator_adaptor<Iterator1,Policies,Value1,Reference1,Pointer1,Category,Distance>& x,
 
921
    const iterator_adaptor<Iterator2,Policies,Value2,Reference2,Pointer2,Category,Distance>& y)
 
922
{
 
923
    return x.policies().distance(y, x) > 0;
 
924
}
 
925
 
 
926
template <class Iterator1, class Iterator2, class Policies, class Value1, class Value2,
 
927
    class Reference1, class Reference2, class Pointer1, class Pointer2,
 
928
    class Category, class Distance>
 
929
inline bool
 
930
operator>=(
 
931
    const iterator_adaptor<Iterator1,Policies,Value1,Reference1,Pointer1,Category,Distance>& x,
 
932
    const iterator_adaptor<Iterator2,Policies,Value2,Reference2,Pointer2,Category,Distance>& y)
 
933
{
 
934
    return x.policies().distance(y, x) >= 0;
 
935
}
 
936
 
 
937
template <class Iterator1, class Iterator2, class Policies, class Value1, class Value2,
 
938
    class Reference1, class Reference2, class Pointer1, class Pointer2,
 
939
    class Category, class Distance>
 
940
inline bool
 
941
operator<=(
 
942
    const iterator_adaptor<Iterator1,Policies,Value1,Reference1,Pointer1,Category,Distance>& x,
 
943
    const iterator_adaptor<Iterator2,Policies,Value2,Reference2,Pointer2,Category,Distance>& y)
 
944
{
 
945
    return x.policies().distance(y, x) <= 0;
 
946
}
 
947
 
 
948
template <class Iterator1, class Iterator2, class Policies, class Value1, class Value2,
 
949
    class Reference1, class Reference2, class Pointer1, class Pointer2,
 
950
    class Category, class Distance>
 
951
inline bool
 
952
operator!=(
 
953
    const iterator_adaptor<Iterator1,Policies,Value1,Reference1,Pointer1,Category,Distance>& x,
 
954
    const iterator_adaptor<Iterator2,Policies,Value2,Reference2,Pointer2,Category,Distance>& y)
 
955
{
 
956
    return !x.policies().equal(x, y);
 
957
}
 
958
#endif
 
959
 
 
960
 
 
961
} // namespace multi_array
 
962
} // namespace detail
 
963
} // namespace boost
 
964
# undef BOOST_ARG_DEPENDENT_TYPENAME
 
965
 
 
966
 
 
967
#endif
 
968
 
 
969
 
 
970