os/ossrv/ossrv_pub/boost_apis/boost/pending/container_traits.hpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
//  (C) Copyright Jeremy Siek 2004 
sl@0
     2
//  Distributed under the Boost Software License, Version 1.0. (See
sl@0
     3
//  accompanying file LICENSE_1_0.txt or copy at
sl@0
     4
//  http://www.boost.org/LICENSE_1_0.txt)
sl@0
     5
sl@0
     6
#ifndef BOOST_GRAPH_DETAIL_CONTAINER_TRAITS_H
sl@0
     7
#define BOOST_GRAPH_DETAIL_CONTAINER_TRAITS_H
sl@0
     8
sl@0
     9
// Sure would be nice to be able to forward declare these
sl@0
    10
// instead of pulling in all the headers. Too bad that
sl@0
    11
// is not legal. There ought to be a standard <stlfwd> header. -JGS 
sl@0
    12
sl@0
    13
#include <boost/next_prior.hpp>
sl@0
    14
sl@0
    15
#include <algorithm>   // for std::remove
sl@0
    16
#include <vector>
sl@0
    17
#include <list>
sl@0
    18
#include <map>
sl@0
    19
#include <set>
sl@0
    20
sl@0
    21
#if !defined BOOST_NO_HASH
sl@0
    22
#  ifdef BOOST_HASH_SET_HEADER
sl@0
    23
#    include BOOST_HASH_SET_HEADER
sl@0
    24
#  else
sl@0
    25
#    include <hash_set>
sl@0
    26
#  endif
sl@0
    27
#  ifdef BOOST_HASH_MAP_HEADER
sl@0
    28
#    include BOOST_HASH_MAP_HEADER
sl@0
    29
#  else
sl@0
    30
#    include <hash_map>
sl@0
    31
#  endif
sl@0
    32
#endif
sl@0
    33
sl@0
    34
#if !defined BOOST_NO_SLIST
sl@0
    35
#  ifdef BOOST_SLIST_HEADER
sl@0
    36
#    include BOOST_SLIST_HEADER
sl@0
    37
#  else
sl@0
    38
#    include <slist>
sl@0
    39
#  endif
sl@0
    40
#endif
sl@0
    41
sl@0
    42
// The content of this file is in 'graph_detail' because otherwise
sl@0
    43
// there will be name clashes with 
sl@0
    44
// sandbox/boost/sequence_algo/container_traits.hpp
sl@0
    45
// The 'detail' subnamespace will still cause problems.
sl@0
    46
namespace boost { namespace graph_detail {
sl@0
    47
sl@0
    48
  //======================================================================
sl@0
    49
  // Container Category Tags
sl@0
    50
  //
sl@0
    51
  //   They use virtual inheritance because there are lots of
sl@0
    52
  //   inheritance diamonds.
sl@0
    53
sl@0
    54
  struct container_tag { };
sl@0
    55
  struct forward_container_tag : virtual public container_tag { };
sl@0
    56
  struct reversible_container_tag : virtual public forward_container_tag { };
sl@0
    57
  struct random_access_container_tag
sl@0
    58
    : virtual public reversible_container_tag { };
sl@0
    59
  
sl@0
    60
  struct sequence_tag : virtual public forward_container_tag { };
sl@0
    61
sl@0
    62
  struct associative_container_tag : virtual public forward_container_tag { };
sl@0
    63
sl@0
    64
  struct sorted_associative_container_tag 
sl@0
    65
    : virtual public associative_container_tag,
sl@0
    66
      virtual public reversible_container_tag { };
sl@0
    67
sl@0
    68
  struct front_insertion_sequence_tag : virtual public sequence_tag { };
sl@0
    69
  struct back_insertion_sequence_tag : virtual public sequence_tag { };
sl@0
    70
sl@0
    71
  struct unique_associative_container_tag 
sl@0
    72
    : virtual public associative_container_tag { };
sl@0
    73
  struct multiple_associative_container_tag 
sl@0
    74
    : virtual public associative_container_tag { };
sl@0
    75
  struct simple_associative_container_tag 
sl@0
    76
    : virtual public associative_container_tag { };
sl@0
    77
  struct pair_associative_container_tag 
sl@0
    78
    : virtual public associative_container_tag { };
sl@0
    79
sl@0
    80
sl@0
    81
  //======================================================================
sl@0
    82
  // Iterator Stability Tags
sl@0
    83
  //
sl@0
    84
  // Do mutating operations such as insert/erase/resize invalidate all
sl@0
    85
  // outstanding iterators?
sl@0
    86
sl@0
    87
  struct stable_tag { };
sl@0
    88
  struct unstable_tag { };
sl@0
    89
sl@0
    90
  //======================================================================
sl@0
    91
  // Container Traits Class and container_category() function
sl@0
    92
sl@0
    93
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
sl@0
    94
  // don't use this unless there is partial specialization 
sl@0
    95
  template <class Container>
sl@0
    96
  struct container_traits {
sl@0
    97
    typedef typename Container::category category;
sl@0
    98
    typedef typename Container::iterator_stability iterator_stability;
sl@0
    99
  };
sl@0
   100
#endif
sl@0
   101
sl@0
   102
  // Use this as a compile-time assertion that X is stable
sl@0
   103
  inline void require_stable(stable_tag) { }
sl@0
   104
sl@0
   105
  // std::vector
sl@0
   106
  struct vector_tag :
sl@0
   107
    virtual public random_access_container_tag,
sl@0
   108
    virtual public back_insertion_sequence_tag { };
sl@0
   109
sl@0
   110
  template <class T, class Alloc>
sl@0
   111
  vector_tag container_category(const std::vector<T,Alloc>&)
sl@0
   112
    { return vector_tag(); }
sl@0
   113
sl@0
   114
  template <class T, class Alloc>
sl@0
   115
  unstable_tag iterator_stability(const std::vector<T,Alloc>&)
sl@0
   116
    { return unstable_tag(); }
sl@0
   117
sl@0
   118
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
sl@0
   119
  template <class T, class Alloc>
sl@0
   120
  struct container_traits< std::vector<T,Alloc> > {
sl@0
   121
    typedef vector_tag category;
sl@0
   122
    typedef unstable_tag iterator_stability;
sl@0
   123
  };
sl@0
   124
#endif
sl@0
   125
sl@0
   126
  // std::list
sl@0
   127
  struct list_tag :
sl@0
   128
    virtual public reversible_container_tag,
sl@0
   129
    virtual public back_insertion_sequence_tag
sl@0
   130
    // this causes problems for push_dispatch...
sl@0
   131
    //    virtual public front_insertion_sequence_tag
sl@0
   132
    { };
sl@0
   133
sl@0
   134
  template <class T, class Alloc>
sl@0
   135
  list_tag container_category(const std::list<T,Alloc>&)
sl@0
   136
    { return list_tag(); }
sl@0
   137
sl@0
   138
  template <class T, class Alloc>
sl@0
   139
  stable_tag iterator_stability(const std::list<T,Alloc>&)
sl@0
   140
    { return stable_tag(); }
sl@0
   141
sl@0
   142
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
sl@0
   143
  template <class T, class Alloc>
sl@0
   144
  struct container_traits< std::list<T,Alloc> > {
sl@0
   145
    typedef list_tag category;
sl@0
   146
    typedef stable_tag iterator_stability;
sl@0
   147
  };
sl@0
   148
#endif
sl@0
   149
sl@0
   150
sl@0
   151
  // std::slist
sl@0
   152
#ifndef BOOST_NO_SLIST
sl@0
   153
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
sl@0
   154
  template <class T, class Alloc>
sl@0
   155
  struct container_traits<BOOST_STD_EXTENSION_NAMESPACE::slist<T,Alloc> > {
sl@0
   156
    typedef front_insertion_sequence_tag category;
sl@0
   157
    typedef stable_tag iterator_stability;
sl@0
   158
  };
sl@0
   159
#endif
sl@0
   160
  template <class T, class Alloc>
sl@0
   161
  front_insertion_sequence_tag container_category(
sl@0
   162
  const BOOST_STD_EXTENSION_NAMESPACE::slist<T,Alloc>&
sl@0
   163
  )
sl@0
   164
    { return front_insertion_sequence_tag(); }
sl@0
   165
sl@0
   166
  template <class T, class Alloc>
sl@0
   167
  stable_tag iterator_stability(
sl@0
   168
  const BOOST_STD_EXTENSION_NAMESPACE::slist<T,Alloc>&)
sl@0
   169
    { return stable_tag(); }
sl@0
   170
#endif
sl@0
   171
sl@0
   172
sl@0
   173
  // std::set
sl@0
   174
  struct set_tag :
sl@0
   175
    virtual public sorted_associative_container_tag,
sl@0
   176
    virtual public simple_associative_container_tag,
sl@0
   177
    virtual public unique_associative_container_tag 
sl@0
   178
    { };
sl@0
   179
sl@0
   180
  template <class Key, class Cmp, class Alloc> 
sl@0
   181
  set_tag container_category(const std::set<Key,Cmp,Alloc>&)
sl@0
   182
  { return set_tag(); }
sl@0
   183
sl@0
   184
  template <class Key, class Cmp, class Alloc> 
sl@0
   185
  stable_tag iterator_stability(const std::set<Key,Cmp,Alloc>&)
sl@0
   186
  { return stable_tag(); }
sl@0
   187
sl@0
   188
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
sl@0
   189
  template <class Key, class Cmp, class Alloc> 
sl@0
   190
  struct container_traits< std::set<Key,Cmp,Alloc> > {
sl@0
   191
    typedef set_tag category;
sl@0
   192
    typedef stable_tag iterator_stability;
sl@0
   193
  };
sl@0
   194
#endif
sl@0
   195
sl@0
   196
  // std::multiset
sl@0
   197
  struct multiset_tag :
sl@0
   198
    virtual public sorted_associative_container_tag,
sl@0
   199
    virtual public simple_associative_container_tag,
sl@0
   200
    virtual public multiple_associative_container_tag 
sl@0
   201
    { };
sl@0
   202
sl@0
   203
  template <class Key, class Cmp, class Alloc> 
sl@0
   204
  multiset_tag container_category(const std::multiset<Key,Cmp,Alloc>&)
sl@0
   205
  { return multiset_tag(); }
sl@0
   206
sl@0
   207
  template <class Key, class Cmp, class Alloc> 
sl@0
   208
  stable_tag iterator_stability(const std::multiset<Key,Cmp,Alloc>&)
sl@0
   209
  { return stable_tag(); }
sl@0
   210
sl@0
   211
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
sl@0
   212
  template <class Key, class Cmp, class Alloc> 
sl@0
   213
  struct container_traits< std::multiset<Key,Cmp,Alloc> > {
sl@0
   214
    typedef multiset_tag category;
sl@0
   215
    typedef stable_tag iterator_stability;
sl@0
   216
  };
sl@0
   217
#endif
sl@0
   218
sl@0
   219
  // deque
sl@0
   220
sl@0
   221
  // std::map
sl@0
   222
  struct map_tag :
sl@0
   223
    virtual public sorted_associative_container_tag,
sl@0
   224
    virtual public pair_associative_container_tag,
sl@0
   225
    virtual public unique_associative_container_tag 
sl@0
   226
    { };
sl@0
   227
sl@0
   228
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
sl@0
   229
  template <class Key, class T, class Cmp, class Alloc> 
sl@0
   230
  struct container_traits< std::map<Key,T,Cmp,Alloc> > {
sl@0
   231
    typedef map_tag category;
sl@0
   232
    typedef stable_tag iterator_stability;
sl@0
   233
  };
sl@0
   234
#endif
sl@0
   235
sl@0
   236
  template <class Key, class T, class Cmp, class Alloc> 
sl@0
   237
  map_tag container_category(const std::map<Key,T,Cmp,Alloc>&)
sl@0
   238
  { return map_tag(); }
sl@0
   239
sl@0
   240
  template <class Key, class T, class Cmp, class Alloc> 
sl@0
   241
  stable_tag iterator_stability(const std::map<Key,T,Cmp,Alloc>&)
sl@0
   242
  { return stable_tag(); }
sl@0
   243
sl@0
   244
  // std::multimap
sl@0
   245
  struct multimap_tag :
sl@0
   246
    virtual public sorted_associative_container_tag,
sl@0
   247
    virtual public pair_associative_container_tag,
sl@0
   248
    virtual public multiple_associative_container_tag 
sl@0
   249
    { };
sl@0
   250
sl@0
   251
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
sl@0
   252
  template <class Key, class T, class Cmp, class Alloc> 
sl@0
   253
  struct container_traits< std::multimap<Key,T,Cmp,Alloc> > {
sl@0
   254
    typedef multimap_tag category;
sl@0
   255
    typedef stable_tag iterator_stability;
sl@0
   256
  };
sl@0
   257
#endif
sl@0
   258
sl@0
   259
  template <class Key, class T, class Cmp, class Alloc> 
sl@0
   260
  multimap_tag container_category(const std::multimap<Key,T,Cmp,Alloc>&)
sl@0
   261
  { return multimap_tag(); }
sl@0
   262
sl@0
   263
  template <class Key, class T, class Cmp, class Alloc> 
sl@0
   264
  stable_tag iterator_stability(const std::multimap<Key,T,Cmp,Alloc>&)
sl@0
   265
  { return stable_tag(); }
sl@0
   266
sl@0
   267
sl@0
   268
 // hash_set, hash_map
sl@0
   269
sl@0
   270
#ifndef BOOST_NO_HASH
sl@0
   271
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
sl@0
   272
  template <class Key, class Eq, class Hash, class Alloc> 
sl@0
   273
  struct container_traits< BOOST_STD_EXTENSION_NAMESPACE::hash_set<Key,Eq,Hash,Alloc> > {
sl@0
   274
    typedef set_tag category;
sl@0
   275
    typedef stable_tag iterator_stability; // is this right?
sl@0
   276
  };
sl@0
   277
  template <class Key, class T, class Eq, class Hash, class Alloc>
sl@0
   278
  struct container_traits< BOOST_STD_EXTENSION_NAMESPACE::hash_map<Key,T,Eq,Hash,Alloc> > {
sl@0
   279
    typedef map_tag category;
sl@0
   280
    typedef stable_tag iterator_stability; // is this right?
sl@0
   281
  };
sl@0
   282
#endif
sl@0
   283
  template <class Key, class Eq, class Hash, class Alloc>
sl@0
   284
  set_tag container_category(const BOOST_STD_EXTENSION_NAMESPACE::hash_set<Key,Eq,Hash,Alloc>&)
sl@0
   285
  { return set_tag(); }
sl@0
   286
sl@0
   287
  template <class Key, class T, class Eq, class Hash, class Alloc>
sl@0
   288
  map_tag container_category(const BOOST_STD_EXTENSION_NAMESPACE::hash_map<Key,T,Eq,Hash,Alloc>&)
sl@0
   289
  { return map_tag(); }
sl@0
   290
sl@0
   291
  template <class Key, class Eq, class Hash, class Alloc>
sl@0
   292
  stable_tag iterator_stability(const BOOST_STD_EXTENSION_NAMESPACE::hash_set<Key,Eq,Hash,Alloc>&)
sl@0
   293
  { return stable_tag(); }
sl@0
   294
sl@0
   295
  template <class Key, class T, class Eq, class Hash, class Alloc>
sl@0
   296
  stable_tag iterator_stability(const BOOST_STD_EXTENSION_NAMESPACE::hash_map<Key,T,Eq,Hash,Alloc>&)
sl@0
   297
  { return stable_tag(); }
sl@0
   298
#endif
sl@0
   299
sl@0
   300
sl@0
   301
sl@0
   302
  //===========================================================================
sl@0
   303
  // Generalized Container Functions
sl@0
   304
sl@0
   305
sl@0
   306
  // Erase
sl@0
   307
  template <class Sequence, class T>
sl@0
   308
  void erase_dispatch(Sequence& c, const T& x, 
sl@0
   309
                      sequence_tag)
sl@0
   310
  {
sl@0
   311
    c.erase(std::remove(c.begin(), c.end(), x), c.end());
sl@0
   312
  }
sl@0
   313
sl@0
   314
  template <class AssociativeContainer, class T>
sl@0
   315
  void erase_dispatch(AssociativeContainer& c, const T& x, 
sl@0
   316
                      associative_container_tag)
sl@0
   317
  {
sl@0
   318
    c.erase(x);
sl@0
   319
  }
sl@0
   320
  template <class Container, class T>
sl@0
   321
  void erase(Container& c, const T& x)
sl@0
   322
  {
sl@0
   323
    erase_dispatch(c, x, container_category(c));
sl@0
   324
  }
sl@0
   325
sl@0
   326
  // Erase If
sl@0
   327
  template <class Sequence, class Predicate, class IteratorStability>
sl@0
   328
  void erase_if_dispatch(Sequence& c, Predicate p,
sl@0
   329
                         sequence_tag, IteratorStability)
sl@0
   330
  {
sl@0
   331
#if 0
sl@0
   332
    c.erase(std::remove_if(c.begin(), c.end(), p), c.end());
sl@0
   333
#else
sl@0
   334
    if (! c.empty())
sl@0
   335
      c.erase(std::remove_if(c.begin(), c.end(), p), c.end());
sl@0
   336
#endif
sl@0
   337
  }
sl@0
   338
  template <class AssociativeContainer, class Predicate>
sl@0
   339
  void erase_if_dispatch(AssociativeContainer& c, Predicate p,
sl@0
   340
                         associative_container_tag, stable_tag)
sl@0
   341
  {
sl@0
   342
    typename AssociativeContainer::iterator i, next;
sl@0
   343
    for (i = next = c.begin(); next != c.end(); i = next) {
sl@0
   344
      ++next;
sl@0
   345
      if (p(*i))
sl@0
   346
        c.erase(i);
sl@0
   347
    }
sl@0
   348
  }
sl@0
   349
  template <class AssociativeContainer, class Predicate>
sl@0
   350
  void erase_if_dispatch(AssociativeContainer& c, Predicate p,
sl@0
   351
                         associative_container_tag, unstable_tag)
sl@0
   352
  {
sl@0
   353
    // This method is really slow, so hopefully we won't have any
sl@0
   354
    // associative containers with unstable iterators!
sl@0
   355
    // Is there a better way to do this?
sl@0
   356
    typename AssociativeContainer::iterator i;
sl@0
   357
    typename AssociativeContainer::size_type n = c.size();
sl@0
   358
    while (n--)
sl@0
   359
      for (i = c.begin(); i != c.end(); ++i)
sl@0
   360
        if (p(*i)) {
sl@0
   361
          c.erase(i);
sl@0
   362
          break;
sl@0
   363
        }
sl@0
   364
  }
sl@0
   365
  template <class Container, class Predicate>
sl@0
   366
  void erase_if(Container& c, Predicate p)
sl@0
   367
  {
sl@0
   368
    erase_if_dispatch(c, p, container_category(c), iterator_stability(c));
sl@0
   369
  }
sl@0
   370
sl@0
   371
  // Push
sl@0
   372
  template <class Container, class T>
sl@0
   373
  std::pair<typename Container::iterator, bool>
sl@0
   374
  push_dispatch(Container& c, const T& v, back_insertion_sequence_tag)
sl@0
   375
  {
sl@0
   376
    c.push_back(v);
sl@0
   377
    return std::make_pair(boost::prior(c.end()), true);
sl@0
   378
  }
sl@0
   379
sl@0
   380
  template <class Container, class T>
sl@0
   381
  std::pair<typename Container::iterator, bool>
sl@0
   382
  push_dispatch(Container& c, const T& v, front_insertion_sequence_tag)
sl@0
   383
  {
sl@0
   384
    c.push_front(v);
sl@0
   385
    return std::make_pair(c.begin(), true);
sl@0
   386
  }
sl@0
   387
sl@0
   388
  template <class AssociativeContainer, class T>
sl@0
   389
  std::pair<typename AssociativeContainer::iterator, bool>
sl@0
   390
  push_dispatch(AssociativeContainer& c, const T& v, 
sl@0
   391
                unique_associative_container_tag)
sl@0
   392
  {
sl@0
   393
    return c.insert(v);
sl@0
   394
  }
sl@0
   395
sl@0
   396
  template <class AssociativeContainer, class T>
sl@0
   397
  std::pair<typename AssociativeContainer::iterator, bool>
sl@0
   398
  push_dispatch(AssociativeContainer& c, const T& v,
sl@0
   399
                multiple_associative_container_tag)
sl@0
   400
  {
sl@0
   401
    return std::make_pair(c.insert(v), true);
sl@0
   402
  }
sl@0
   403
sl@0
   404
  template <class Container, class T>
sl@0
   405
  std::pair<typename Container::iterator,bool>
sl@0
   406
  push(Container& c, const T& v)
sl@0
   407
  {
sl@0
   408
    return push_dispatch(c, v, container_category(c));
sl@0
   409
  }
sl@0
   410
sl@0
   411
}} // namespace boost::graph_detail
sl@0
   412
sl@0
   413
#endif // BOOST_GRAPH_DETAIL_CONTAINER_TRAITS_H