Coverage Report

Created: 2023-06-07 06:18

/src/boost/boost/multi_index/detail/ord_index_node.hpp
Line
Count
Source (jump to first uncovered line)
1
/* Copyright 2003-2020 Joaquin M Lopez Munoz.
2
 * Distributed under the Boost Software License, Version 1.0.
3
 * (See accompanying file LICENSE_1_0.txt or copy at
4
 * http://www.boost.org/LICENSE_1_0.txt)
5
 *
6
 * See http://www.boost.org/libs/multi_index for library home page.
7
 *
8
 * The internal implementation of red-black trees is based on that of SGI STL
9
 * stl_tree.h file: 
10
 *
11
 * Copyright (c) 1996,1997
12
 * Silicon Graphics Computer Systems, Inc.
13
 *
14
 * Permission to use, copy, modify, distribute and sell this software
15
 * and its documentation for any purpose is hereby granted without fee,
16
 * provided that the above copyright notice appear in all copies and
17
 * that both that copyright notice and this permission notice appear
18
 * in supporting documentation.  Silicon Graphics makes no
19
 * representations about the suitability of this software for any
20
 * purpose.  It is provided "as is" without express or implied warranty.
21
 *
22
 *
23
 * Copyright (c) 1994
24
 * Hewlett-Packard Company
25
 *
26
 * Permission to use, copy, modify, distribute and sell this software
27
 * and its documentation for any purpose is hereby granted without fee,
28
 * provided that the above copyright notice appear in all copies and
29
 * that both that copyright notice and this permission notice appear
30
 * in supporting documentation.  Hewlett-Packard Company makes no
31
 * representations about the suitability of this software for any
32
 * purpose.  It is provided "as is" without express or implied warranty.
33
 *
34
 */
35
36
#ifndef BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_NODE_HPP
37
#define BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_NODE_HPP
38
39
#if defined(_MSC_VER)
40
#pragma once
41
#endif
42
43
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
44
#include <cstddef>
45
#include <boost/multi_index/detail/allocator_traits.hpp>
46
#include <boost/multi_index/detail/raw_ptr.hpp>
47
48
#if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
49
#include <boost/mpl/and.hpp>
50
#include <boost/mpl/if.hpp>
51
#include <boost/multi_index/detail/uintptr_type.hpp>
52
#include <boost/type_traits/alignment_of.hpp>
53
#include <boost/type_traits/is_same.hpp>
54
#endif
55
56
namespace boost{
57
58
namespace multi_index{
59
60
namespace detail{
61
62
/* definition of red-black nodes for ordered_index */
63
64
enum ordered_index_color{red=false,black=true};
65
enum ordered_index_side{to_left=false,to_right=true};
66
67
template<typename AugmentPolicy,typename Allocator>
68
struct ordered_index_node_impl; /* fwd decl. */
69
70
template<typename AugmentPolicy,typename Allocator>
71
struct ordered_index_node_traits
72
{
73
  typedef typename rebind_alloc_for<
74
    Allocator,
75
    ordered_index_node_impl<AugmentPolicy,Allocator>
76
  >::type                                            allocator;
77
  typedef allocator_traits<allocator>                alloc_traits;
78
  typedef typename alloc_traits::pointer             pointer;
79
  typedef typename alloc_traits::const_pointer       const_pointer;
80
  typedef typename alloc_traits::difference_type     difference_type;
81
  typedef typename alloc_traits::size_type           size_type;
82
};
83
84
template<typename AugmentPolicy,typename Allocator>
85
struct ordered_index_node_std_base
86
{
87
  typedef ordered_index_node_traits<
88
    AugmentPolicy,Allocator>                    node_traits;
89
  typedef typename node_traits::allocator       node_allocator;
90
  typedef typename node_traits::pointer         pointer;
91
  typedef typename node_traits::const_pointer   const_pointer;
92
  typedef typename node_traits::difference_type difference_type;
93
  typedef typename node_traits::size_type       size_type;
94
  typedef ordered_index_color&                  color_ref;
95
  typedef pointer&                              parent_ref;
96
97
  ordered_index_color& color(){return color_;}
98
  ordered_index_color  color()const{return color_;}
99
  pointer&             parent(){return parent_;}
100
  pointer              parent()const{return parent_;}
101
  pointer&             left(){return left_;}
102
  pointer              left()const{return left_;}
103
  pointer&             right(){return right_;}
104
  pointer              right()const{return right_;}
105
106
private:
107
  ordered_index_color color_; 
108
  pointer             parent_;
109
  pointer             left_;
110
  pointer             right_;
111
};
112
113
#if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
114
/* If ordered_index_node_impl has even alignment, we can use the least
115
 * significant bit of one of the ordered_index_node_impl pointers to
116
 * store color information. This typically reduces the size of
117
 * ordered_index_node_impl by 25%.
118
 */
119
120
#if defined(BOOST_MSVC)
121
/* This code casts pointers to an integer type that has been computed
122
 * to be large enough to hold the pointer, however the metaprogramming
123
 * logic is not always spotted by the VC++ code analyser that issues a
124
 * long list of warnings.
125
 */
126
127
#pragma warning(push)
128
#pragma warning(disable:4312 4311)
129
#endif
130
131
template<typename AugmentPolicy,typename Allocator>
132
struct ordered_index_node_compressed_base
133
{
134
  typedef ordered_index_node_traits<
135
    AugmentPolicy,Allocator>                    node_traits;
136
  typedef ordered_index_node_impl<
137
    AugmentPolicy,Allocator>*                   pointer;
138
  typedef const ordered_index_node_impl<
139
    AugmentPolicy,Allocator>*                   const_pointer;
140
  typedef typename node_traits::difference_type difference_type;
141
  typedef typename node_traits::size_type       size_type;
142
143
  struct color_ref
144
  {
145
203k
    color_ref(uintptr_type* r_):r(r_){}
146
    color_ref(const color_ref& x):r(x.r){}
147
    
148
    operator ordered_index_color()const
149
46.7k
    {
150
46.7k
      return ordered_index_color(*r&uintptr_type(1));
151
46.7k
    }
152
    
153
    color_ref& operator=(ordered_index_color c)
154
156k
    {
155
156k
      *r&=~uintptr_type(1);
156
156k
      *r|=uintptr_type(c);
157
156k
      return *this;
158
156k
    }
159
    
160
    color_ref& operator=(const color_ref& x)
161
1.45k
    {
162
1.45k
      return operator=(x.operator ordered_index_color());
163
1.45k
    }
164
    
165
  private:
166
    uintptr_type* r;
167
  };
168
  
169
  struct parent_ref
170
  {
171
511k
    parent_ref(uintptr_type* r_):r(r_){}
172
12.3k
    parent_ref(const parent_ref& x):r(x.r){}
173
    
174
    operator pointer()const
175
432k
    {
176
432k
      return (pointer)(void*)(*r&~uintptr_type(1));
177
432k
    }
178
    
179
    parent_ref& operator=(pointer p)
180
135k
    {
181
135k
      *r=((uintptr_type)(void*)p)|(*r&uintptr_type(1));
182
135k
      return *this;
183
135k
    }
184
    
185
    parent_ref& operator=(const parent_ref& x)
186
13.8k
    {
187
13.8k
      return operator=(x.operator pointer());
188
13.8k
    }
189
190
    pointer operator->()const
191
202k
    {
192
202k
      return operator pointer();
193
202k
    }
194
195
  private:
196
    uintptr_type* r;
197
  };
198
  
199
203k
  color_ref           color(){return color_ref(&parentcolor_);}
200
  ordered_index_color color()const
201
  {
202
    return ordered_index_color(parentcolor_&uintptr_type(1));
203
  }
204
205
511k
  parent_ref parent(){return parent_ref(&parentcolor_);}
206
  pointer    parent()const
207
  {
208
    return (pointer)(void*)(parentcolor_&~uintptr_type(1));
209
  }
210
211
275k
  pointer& left(){return left_;}
212
  pointer  left()const{return left_;}
213
254k
  pointer& right(){return right_;}
214
  pointer  right()const{return right_;}
215
216
private:
217
  uintptr_type parentcolor_;
218
  pointer      left_;
219
  pointer      right_;
220
};
221
#if defined(BOOST_MSVC)
222
#pragma warning(pop)
223
#endif
224
#endif
225
226
template<typename AugmentPolicy,typename Allocator>
227
struct ordered_index_node_impl_base:
228
229
#if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
230
  AugmentPolicy::template augmented_node<
231
    typename mpl::if_c<
232
      !(has_uintptr_type::value)||
233
      (alignment_of<
234
        ordered_index_node_compressed_base<AugmentPolicy,Allocator>
235
       >::value%2)||
236
      !(is_same<
237
        typename ordered_index_node_traits<AugmentPolicy,Allocator>::pointer,
238
        ordered_index_node_impl<AugmentPolicy,Allocator>*>::value),
239
      ordered_index_node_std_base<AugmentPolicy,Allocator>,
240
      ordered_index_node_compressed_base<AugmentPolicy,Allocator>
241
    >::type
242
  >::type
243
#else
244
  AugmentPolicy::template augmented_node<
245
    ordered_index_node_std_base<AugmentPolicy,Allocator>
246
  >::type
247
#endif
248
249
{};
250
251
template<typename AugmentPolicy,typename Allocator>
252
struct ordered_index_node_impl:
253
  ordered_index_node_impl_base<AugmentPolicy,Allocator>
254
{
255
private:
256
  typedef ordered_index_node_impl_base<AugmentPolicy,Allocator> super;
257
258
public:
259
  typedef typename super::color_ref                             color_ref;
260
  typedef typename super::parent_ref                            parent_ref;
261
  typedef typename super::pointer                               pointer;
262
  typedef typename super::const_pointer                         const_pointer;
263
264
  /* interoperability with bidir_node_iterator */
265
266
  static void increment(pointer& x)
267
  {
268
    if(x->right()!=pointer(0)){
269
      x=x->right();
270
      while(x->left()!=pointer(0))x=x->left();
271
    }
272
    else{
273
      pointer y=x->parent();
274
      while(x==y->right()){
275
        x=y;
276
        y=y->parent();
277
      }
278
      if(x->right()!=y)x=y;
279
    }
280
  }
281
282
  static void decrement(pointer& x)
283
  {
284
    if(x->color()==red&&x->parent()->parent()==x){
285
      x=x->right();
286
    }
287
    else if(x->left()!=pointer(0)){
288
      pointer y=x->left();
289
      while(y->right()!=pointer(0))y=y->right();
290
      x=y;
291
    }else{
292
      pointer y=x->parent();
293
      while(x==y->left()){
294
        x=y;
295
        y=y->parent();
296
      }
297
      x=y;
298
    }
299
  }
300
301
  /* algorithmic stuff */
302
303
  static void rotate_left(pointer x,parent_ref root)
304
6.17k
  {
305
6.17k
    pointer y=x->right();
306
6.17k
    x->right()=y->left();
307
6.17k
    if(y->left()!=pointer(0))y->left()->parent()=x;
308
6.17k
    y->parent()=x->parent();
309
    
310
6.17k
    if(x==root)                    root=y;
311
5.08k
    else if(x==x->parent()->left())x->parent()->left()=y;
312
1.59k
    else                           x->parent()->right()=y;
313
6.17k
    y->left()=x;
314
6.17k
    x->parent()=y;
315
6.17k
    AugmentPolicy::rotate_left(x,y);
316
6.17k
  }
317
318
  static pointer minimum(pointer x)
319
0
  {
320
0
    while(x->left()!=pointer(0))x=x->left();
321
0
    return x;
322
0
  }
323
324
  static pointer maximum(pointer x)
325
0
  {
326
0
    while(x->right()!=pointer(0))x=x->right();
327
0
    return x;
328
0
  }
329
330
  static void rotate_right(pointer x,parent_ref root)
331
6.17k
  {
332
6.17k
    pointer y=x->left();
333
6.17k
    x->left()=y->right();
334
6.17k
    if(y->right()!=pointer(0))y->right()->parent()=x;
335
6.17k
    y->parent()=x->parent();
336
337
6.17k
    if(x==root)                     root=y;
338
5.11k
    else if(x==x->parent()->right())x->parent()->right()=y;
339
1.72k
    else                            x->parent()->left()=y;
340
6.17k
    y->right()=x;
341
6.17k
    x->parent()=y;
342
6.17k
    AugmentPolicy::rotate_right(x,y);
343
6.17k
  }
344
345
  static void rebalance(pointer x,parent_ref root)
346
19.3k
  {
347
19.3k
    x->color()=red;
348
34.0k
    while(x!=root&&x->parent()->color()==red){
349
14.6k
      if(x->parent()==x->parent()->parent()->left()){
350
7.38k
        pointer y=x->parent()->parent()->right();
351
7.38k
        if(y!=pointer(0)&&y->color()==red){
352
3.20k
          x->parent()->color()=black;
353
3.20k
          y->color()=black;
354
3.20k
          x->parent()->parent()->color()=red;
355
3.20k
          x=x->parent()->parent();
356
3.20k
        }
357
4.17k
        else{
358
4.17k
          if(x==x->parent()->right()){
359
2.15k
            x=x->parent();
360
2.15k
            rotate_left(x,root);
361
2.15k
          }
362
4.17k
          x->parent()->color()=black;
363
4.17k
          x->parent()->parent()->color()=red;
364
4.17k
          rotate_right(x->parent()->parent(),root);
365
4.17k
        }
366
7.38k
      }
367
7.31k
      else{
368
7.31k
        pointer y=x->parent()->parent()->left();
369
7.31k
        if(y!=pointer(0)&&y->color()==red){
370
3.29k
          x->parent()->color()=black;
371
3.29k
          y->color()=black;
372
3.29k
          x->parent()->parent()->color()=red;
373
3.29k
          x=x->parent()->parent();
374
3.29k
        }
375
4.01k
        else{
376
4.01k
          if(x==x->parent()->left()){
377
2.00k
            x=x->parent();
378
2.00k
            rotate_right(x,root);
379
2.00k
          }
380
4.01k
          x->parent()->color()=black;
381
4.01k
          x->parent()->parent()->color()=red;
382
4.01k
          rotate_left(x->parent()->parent(),root);
383
4.01k
        }
384
7.31k
      }
385
14.6k
    }
386
19.3k
    root->color()=black;
387
19.3k
  }
388
389
  static void link(
390
    pointer x,ordered_index_side side,pointer position,pointer header)
391
19.3k
  {
392
19.3k
    if(side==to_left){
393
11.1k
      position->left()=x;  /* also makes leftmost=x when parent==header */
394
11.1k
      if(position==header){
395
2.84k
        header->parent()=x;
396
2.84k
        header->right()=x;
397
2.84k
      }
398
8.29k
      else if(position==header->left()){
399
3.01k
        header->left()=x;  /* maintain leftmost pointing to min node */
400
3.01k
      }
401
11.1k
    }
402
8.17k
    else{
403
8.17k
      position->right()=x;
404
8.17k
      if(position==header->right()){
405
2.76k
        header->right()=x; /* maintain rightmost pointing to max node */
406
2.76k
      }
407
8.17k
    }
408
19.3k
    x->parent()=position;
409
19.3k
    x->left()=pointer(0);
410
19.3k
    x->right()=pointer(0);
411
19.3k
    AugmentPolicy::add(x,pointer(header->parent()));
412
19.3k
    ordered_index_node_impl::rebalance(x,header->parent());
413
19.3k
  }
414
415
  static pointer rebalance_for_extract(
416
    pointer z,parent_ref root,pointer& leftmost,pointer& rightmost)
417
5.28k
  {
418
5.28k
    pointer y=z;
419
5.28k
    pointer x=pointer(0);
420
5.28k
    pointer x_parent=pointer(0);
421
5.28k
    if(y->left()==pointer(0)){    /* z has at most one non-null child. y==z. */
422
3.82k
      x=y->right();               /* x might be null */
423
3.82k
    }
424
1.45k
    else{
425
1.45k
      if(y->right()==pointer(0)){ /* z has exactly one non-null child. y==z. */
426
0
        x=y->left();              /* x is not null */
427
0
      }
428
1.45k
      else{                       /* z has two non-null children.  Set y to */
429
1.45k
        y=y->right();             /* z's successor. x might be null.        */
430
1.45k
        while(y->left()!=pointer(0))y=y->left();
431
1.45k
        x=y->right();
432
1.45k
      }
433
1.45k
    }
434
5.28k
    AugmentPolicy::remove(y,pointer(root));
435
5.28k
    if(y!=z){
436
1.45k
      AugmentPolicy::copy(z,y);
437
1.45k
      z->left()->parent()=y;   /* relink y in place of z. y is z's successor */
438
1.45k
      y->left()=z->left();
439
1.45k
      if(y!=z->right()){
440
0
        x_parent=y->parent();
441
0
        if(x!=pointer(0))x->parent()=y->parent();
442
0
        y->parent()->left()=x; /* y must be a child of left */
443
0
        y->right()=z->right();
444
0
        z->right()->parent()=y;
445
0
      }
446
1.45k
      else{
447
1.45k
        x_parent=y;
448
1.45k
      }
449
450
1.45k
      if(root==z)                    root=y;
451
882
      else if(z->parent()->left()==z)z->parent()->left()=y;
452
293
      else                           z->parent()->right()=y;
453
1.45k
      y->parent()=z->parent();
454
1.45k
      ordered_index_color c=y->color();
455
1.45k
      y->color()=z->color();
456
1.45k
      z->color()=c;
457
1.45k
      y=z;                    /* y now points to node to be actually deleted */
458
1.45k
    }
459
3.82k
    else{                     /* y==z */
460
3.82k
      x_parent=y->parent();
461
3.82k
      if(x!=pointer(0))x->parent()=y->parent();   
462
3.82k
      if(root==z){
463
1.18k
        root=x;
464
1.18k
      }
465
2.64k
      else{
466
2.64k
        if(z->parent()->left()==z)z->parent()->left()=x;
467
688
        else                      z->parent()->right()=x;
468
2.64k
      }
469
3.82k
      if(leftmost==z){
470
2.79k
        if(z->right()==pointer(0)){ /* z->left() must be null also */
471
2.79k
          leftmost=z->parent();
472
2.79k
        }
473
0
        else{              
474
0
          leftmost=minimum(x);      /* makes leftmost==header if z==root */
475
0
        }
476
2.79k
      }
477
3.82k
      if(rightmost==z){
478
1.86k
        if(z->left()==pointer(0)){  /* z->right() must be null also */
479
1.86k
          rightmost=z->parent();
480
1.86k
        }
481
0
        else{                   /* x==z->left() */
482
0
          rightmost=maximum(x); /* makes rightmost==header if z==root */
483
0
        }
484
1.86k
      }
485
3.82k
    }
486
5.28k
    if(y->color()!=red){
487
1.18k
      while(x!=root&&(x==pointer(0)|| x->color()==black)){
488
0
        if(x==x_parent->left()){
489
0
          pointer w=x_parent->right();
490
0
          if(w->color()==red){
491
0
            w->color()=black;
492
0
            x_parent->color()=red;
493
0
            rotate_left(x_parent,root);
494
0
            w=x_parent->right();
495
0
          }
496
0
          if((w->left()==pointer(0)||w->left()->color()==black) &&
497
0
             (w->right()==pointer(0)||w->right()->color()==black)){
498
0
            w->color()=red;
499
0
            x=x_parent;
500
0
            x_parent=x_parent->parent();
501
0
          } 
502
0
          else{
503
0
            if(w->right()==pointer(0 )
504
0
                || w->right()->color()==black){
505
0
              if(w->left()!=pointer(0)) w->left()->color()=black;
506
0
              w->color()=red;
507
0
              rotate_right(w,root);
508
0
              w=x_parent->right();
509
0
            }
510
0
            w->color()=x_parent->color();
511
0
            x_parent->color()=black;
512
0
            if(w->right()!=pointer(0))w->right()->color()=black;
513
0
            rotate_left(x_parent,root);
514
0
            break;
515
0
          }
516
0
        } 
517
0
        else{                   /* same as above,with right <-> left */
518
0
          pointer w=x_parent->left();
519
0
          if(w->color()==red){
520
0
            w->color()=black;
521
0
            x_parent->color()=red;
522
0
            rotate_right(x_parent,root);
523
0
            w=x_parent->left();
524
0
          }
525
0
          if((w->right()==pointer(0)||w->right()->color()==black) &&
526
0
             (w->left()==pointer(0)||w->left()->color()==black)){
527
0
            w->color()=red;
528
0
            x=x_parent;
529
0
            x_parent=x_parent->parent();
530
0
          }
531
0
          else{
532
0
            if(w->left()==pointer(0)||w->left()->color()==black){
533
0
              if(w->right()!=pointer(0))w->right()->color()=black;
534
0
              w->color()=red;
535
0
              rotate_left(w,root);
536
0
              w=x_parent->left();
537
0
            }
538
0
            w->color()=x_parent->color();
539
0
            x_parent->color()=black;
540
0
            if(w->left()!=pointer(0))w->left()->color()=black;
541
0
            rotate_right(x_parent,root);
542
0
            break;
543
0
          }
544
0
        }
545
0
      }
546
1.18k
      if(x!=pointer(0))x->color()=black;
547
1.18k
    }
548
5.28k
    return y;
549
5.28k
  }
550
551
  static void restore(pointer x,pointer position,pointer header)
552
  {
553
    if(position->left()==pointer(0)||position->left()==header){
554
      link(x,to_left,position,header);
555
    }
556
    else{
557
      decrement(position);
558
      link(x,to_right,position,header);
559
    }
560
  }
561
562
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
563
  /* invariant stuff */
564
565
  static std::size_t black_count(pointer node,pointer root)
566
  {
567
    if(node==pointer(0))return 0;
568
    std::size_t sum=0;
569
    for(;;){
570
      if(node->color()==black)++sum;
571
      if(node==root)break;
572
      node=node->parent();
573
    } 
574
    return sum;
575
  }
576
#endif
577
};
578
579
template<typename AugmentPolicy,typename Super>
580
struct ordered_index_node_trampoline:
581
  ordered_index_node_impl<
582
    AugmentPolicy,
583
    typename rebind_alloc_for<
584
      typename Super::allocator_type,
585
      char
586
    >::type
587
  >
588
{
589
  typedef ordered_index_node_impl<
590
    AugmentPolicy,
591
    typename rebind_alloc_for<
592
      typename Super::allocator_type,
593
      char
594
    >::type
595
  > impl_type;
596
};
597
598
template<typename AugmentPolicy,typename Super>
599
struct ordered_index_node:
600
  Super,ordered_index_node_trampoline<AugmentPolicy,Super>
601
{
602
private:
603
  typedef ordered_index_node_trampoline<AugmentPolicy,Super> trampoline;
604
605
public:
606
  typedef typename trampoline::impl_type       impl_type;
607
  typedef typename trampoline::color_ref       impl_color_ref;
608
  typedef typename trampoline::parent_ref      impl_parent_ref;
609
  typedef typename trampoline::pointer         impl_pointer;
610
  typedef typename trampoline::const_pointer   const_impl_pointer;
611
  typedef typename trampoline::difference_type difference_type;
612
  typedef typename trampoline::size_type       size_type;
613
614
79.0k
  impl_color_ref      color(){return trampoline::color();}
615
  ordered_index_color color()const{return trampoline::color();}
616
180k
  impl_parent_ref     parent(){return trampoline::parent();}
617
  impl_pointer        parent()const{return trampoline::parent();}
618
145k
  impl_pointer&       left(){return trampoline::left();}
619
  impl_pointer        left()const{return trampoline::left();}
620
146k
  impl_pointer&       right(){return trampoline::right();}
621
  impl_pointer        right()const{return trampoline::right();}
622
623
  impl_pointer impl()
624
221k
  {
625
221k
    return static_cast<impl_pointer>(
626
221k
      static_cast<impl_type*>(static_cast<trampoline*>(this)));
627
221k
  }
628
629
  const_impl_pointer impl()const
630
  {
631
    return static_cast<const_impl_pointer>(
632
      static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
633
  }
634
635
  static ordered_index_node* from_impl(impl_pointer x)
636
219k
  {
637
219k
    return
638
219k
      static_cast<ordered_index_node*>(
639
219k
        static_cast<trampoline*>(
640
219k
          raw_ptr<impl_type*>(x)));
641
219k
  }
642
643
  static const ordered_index_node* from_impl(const_impl_pointer x)
644
  {
645
    return
646
      static_cast<const ordered_index_node*>(
647
        static_cast<const trampoline*>(
648
          raw_ptr<const impl_type*>(x)));
649
  }
650
651
  /* interoperability with bidir_node_iterator */
652
653
  static void increment(ordered_index_node*& x)
654
  {
655
    impl_pointer xi=x->impl();
656
    trampoline::increment(xi);
657
    x=from_impl(xi);
658
  }
659
660
  static void decrement(ordered_index_node*& x)
661
  {
662
    impl_pointer xi=x->impl();
663
    trampoline::decrement(xi);
664
    x=from_impl(xi);
665
  }
666
};
667
668
} /* namespace multi_index::detail */
669
670
} /* namespace multi_index */
671
672
} /* namespace boost */
673
674
#endif