GEOS
StdContainerWrappers.hpp
Go to the documentation of this file.
1 #ifndef GEOS_COMMON_STD_CONTAINER_WRAPPERS_HPP
2 #define GEOS_COMMON_STD_CONTAINER_WRAPPERS_HPP
3 
4 #include <array>
5 #include <cstddef>
6 #include <vector>
7 #include <map>
8 #include <unordered_map>
9 #include <memory>
10 
11 #include <iostream>
12 
13 namespace geos
14 {
15 
20 #ifdef GEOS_USE_BOUNDS_CHECK
21 #define USE_STD_CONTAINER_BOUNDS_CHECKING true
22 #else
23 #define USE_STD_CONTAINER_BOUNDS_CHECKING false
24 #endif
25 
26 
43 namespace internal
44 {
45 
46 
47 
54 template< typename T >
55 using DefaultAllocator = std::allocator< T >;
56 
65 template< typename T,
66  typename Allocator = DefaultAllocator< T >,
67  bool USE_BOUNDS_CHECKING = false >
68 class StdVectorWrapper : public std::vector< T, Allocator >
69 {
70 public:
72  using Base = std::vector< T, Allocator >;
73 
76  StdVectorWrapper() noexcept(noexcept(Allocator())): Base( Allocator()) {}
77 
78  explicit StdVectorWrapper( const Allocator & alloc ) noexcept: Base( alloc ) {}
79 
80  explicit StdVectorWrapper( size_t count, const Allocator & alloc = Allocator())
81  : Base( count, alloc ) {}
82 
83  explicit StdVectorWrapper( size_t count, const T & value,
84  const Allocator & alloc = Allocator())
85  : Base( count, value, alloc ) {}
86 
87  template< class InputIt >
88  StdVectorWrapper( InputIt first, InputIt last,
89  const Allocator & alloc = Allocator())
90  : Base( first, last, alloc ) {}
91 
92  StdVectorWrapper( const Base & other ): Base( other ) {}
93 
94  StdVectorWrapper( Base && other ): Base( other ) {}
95 
96  StdVectorWrapper( const Base & other, const Allocator & alloc )
97  : Base( other, alloc ) {}
98 
99  StdVectorWrapper( Base && other, const Allocator & alloc )
100  : Base( other, alloc ) {}
101 
102  StdVectorWrapper( std::initializer_list< T > init,
103  const Allocator & alloc = Allocator())
104  : Base( init, alloc ) {}
105 
107 
108 
116  T const & operator[]( size_t const index ) const
117  {
118  if constexpr (USE_BOUNDS_CHECKING)
119  {
120  if( index >= this->size() )
121  {
122  std::cout<< "Index out of bounds in StdVectorWrapper::operator[]: index = " + std::to_string( index ) + ", size = " + std::to_string( this->size());
123  }
124  return Base::at( index ); // Throws std::out_of_range if out of bounds.
125  }
126  else
127  {
128  return Base::operator[]( index );
129  }
130  }
131 
138  T & operator[]( size_t const index )
139  {
140  if constexpr (USE_BOUNDS_CHECKING)
141  {
142  if( index >= this->size() )
143  {
144  std::cout<< "Index out of bounds in StdVectorWrapper::operator[]: index = " + std::to_string( index ) + ", size = " + std::to_string( this->size());
145  }
146  return Base::at( index ); // Throws std::out_of_range if out of bounds.
147  }
148  else
149  {
150  return Base::operator[]( index ); // No bounds checking
151  }
152  }
153 };
154 }
155 
161 template< typename T, typename Allocator = std::allocator< T > >
162 using stdVector = internal::StdVectorWrapper< T, Allocator, USE_STD_CONTAINER_BOUNDS_CHECKING >;
163 
164 
165 
166 namespace internal
167 {
168 
176 template< typename MapType,
177  bool USE_BOUNDS_CHECKING = false >
178 class StdMapWrapper : public MapType
179 {
180 public:
182  using Base = MapType;
183  using KeyType = typename Base::key_type;
184  using MappedType = typename Base::mapped_type;
185  using ValueType = typename Base::value_type;
186 
188  using Base::Base;
189 
197  MappedType & operator[]( KeyType const & key )
198  {
199  if constexpr (USE_BOUNDS_CHECKING)
200  {
201  return this->at( key ); // Throws std::out_of_range if key is missing
202  }
203  else
204  {
205  return Base::operator[]( key ); // Inserts default-constructed value if missing
206  }
207  }
208 
216  MappedType const & operator[]( KeyType const & key ) const
217  {
218  if constexpr (USE_BOUNDS_CHECKING)
219  {
220  return this->at( key );
221  }
222  else
223  {
224  return Base::operator[]( key );
225  }
226  }
227 
234  auto & get_inserted( KeyType && k )
235  {
236  return this->try_emplace( k ).first->second;
237  }
238 
245  auto & get_inserted( KeyType const & k )
246  {
247  return this->try_emplace( k ).first->second;
248  }
249 
250 };
251 
252 } //namespace internal
253 
261 template< typename Key,
262  typename T,
263  typename Compare = std::less< Key >,
264  typename Allocator = std::allocator< std::pair< const Key, T > > >
265 using stdMap = internal::StdMapWrapper< std::map< Key, T, Compare, Allocator >,
267 
276 template< typename Key,
277  typename T,
278  typename Hash = std::hash< Key >,
279  typename KeyEqual = std::equal_to< Key >,
280  typename Allocator = std::allocator< std::pair< const Key, T > > >
281 using stdUnorderedMap = internal::StdMapWrapper< std::unordered_map< Key, T, Hash, KeyEqual, Allocator >,
283 
288 
290 
295 
302 template< typename TKEY, typename TVAL, typename SORTED >
303 class mapType
304 {};
305 
307 template< typename TKEY, typename TVAL >
308 class mapType< TKEY, TVAL, std::integral_constant< bool, true > > : public stdMap< TKEY, TVAL >
309 {
310  using stdMap< TKEY, TVAL >::stdMap; // enable list initialization
311 };
312 
313 template< typename TKEY, typename TVAL >
314 class mapType< TKEY, TVAL, std::integral_constant< bool, false > > : public stdUnorderedMap< TKEY, TVAL >
315 {
316  using stdUnorderedMap< TKEY, TVAL >::stdUnorderedMap; // enable list initialization
317 };
319 
320 
326 
333 template< typename TKEY, typename TVAL, typename SORTED >
334 class mapBase
335 {};
336 
338 template< typename TKEY, typename TVAL >
339 class mapBase< TKEY, TVAL, std::integral_constant< bool, true > > : public std::map< TKEY, TVAL >
340 {
341  using std::map< TKEY, TVAL >::map; // enable list initialization
342 };
343 
344 template< typename TKEY, typename TVAL >
345 class mapBase< TKEY, TVAL, std::integral_constant< bool, false > > : public std::unordered_map< TKEY, TVAL >
346 {
347  using std::unordered_map< TKEY, TVAL >::unordered_map; // enable list initialization
348 };
350 
351 namespace internal
352 {
353 
361 template< class T,
362  std::size_t N,
363  bool USE_BOUNDS_CHECKING = false >
364 struct StdArrayWrapper : public std::array< T, N >
365 {
366 public:
368  using Base = std::array< T, N >;
369 
377  constexpr T & operator[]( size_t const index )
378  {
379  if constexpr (USE_BOUNDS_CHECKING)
380  {
381  return this->at( index );
382  }
383  else
384  {
385  return Base::operator[]( index );
386  }
387  }
388 
396  constexpr T const & operator[]( size_t const index ) const
397  {
398  if constexpr (USE_BOUNDS_CHECKING)
399  {
400  return this->at( index );
401  }
402  else
403  {
404  return Base::operator[]( index );
405  }
406  }
407 
408 };
409 } //namespace internal
410 
416 template< class T, std::size_t N >
417 struct stdArray : public internal::StdArrayWrapper< T, N, true >
418 {};
419 
429 template< typename _Tp, typename ... _Up >
430 stdArray( _Tp, _Up ... )
431  ->stdArray< std::enable_if_t< (std::is_same_v< _Tp, _Up > && ...), _Tp >,
432  1 + sizeof...(_Up) >;
433 
442 template< typename T, std::size_t N, std::size_t... Is >
443 constexpr stdArray< T, N > to_stdArray_impl( std::array< T, N > const & arr, std::index_sequence< Is... > )
444 {
445  return {{arr[Is] ...}};
446 }
447 
456 template< typename T, std::size_t N >
457 constexpr stdArray< T, N > to_stdArray( std::array< T, N > const & arr )
458 {
459  return to_stdArray_impl( arr, std::make_index_sequence< N >{} );
460 }
461 
462 
463 } // namespace geos
464 
465 #endif /* GEOS_COMMON_STD_CONTAINER_WRAPPERS_HPP */
#define USE_STD_CONTAINER_BOUNDS_CHECKING
Compile-time flag that enables or disables runtime bounds checking in GEOS container wrappers.
Base template for ordered and unordered maps.
Base template for ordered and unordered maps.
internal::StdMapWrapper< std::unordered_map< Key, T, Hash, KeyEqual, Allocator >, USE_STD_CONTAINER_BOUNDS_CHECKING > stdUnorderedMap
mapBase< TKEY, TVAL, std::integral_constant< bool, false > > unordered_map
Unordered map type.
Definition: DataTypes.hpp:343
constexpr stdArray< T, N > to_stdArray_impl(std::array< T, N > const &arr, std::index_sequence< Is... >)
Helper function that convert a std::array into a stdArray by expanding its elements.
constexpr stdArray< T, N > to_stdArray(std::array< T, N > const &arr)
Convert an std::array to an stdArray.
stdArray(_Tp, _Up ...) -> stdArray< std::enable_if_t<(std::is_same_v< _Tp, _Up > &&...), _Tp >, 1+sizeof...(_Up) >
Deduction guide for stdArray Allows the element type and array size to be automatically deduced from ...
internal::StdMapWrapper< std::map< Key, T, Compare, Allocator >, USE_STD_CONTAINER_BOUNDS_CHECKING > stdMap
std::size_t size_t
Unsigned size type.
Definition: DataTypes.hpp:78
mapBase< TKEY, TVAL, std::integral_constant< bool, true > > map
Ordered map type.
Definition: DataTypes.hpp:339
internal::StdVectorWrapper< T, Allocator, USE_STD_CONTAINER_BOUNDS_CHECKING > stdVector