1 /* 2 * Copyright (c) 2003 3 * Francois Dumont 4 * 5 * This material is provided "as is", with absolutely no warranty expressed 6 * or implied. Any use is at your own risk. 7 * 8 * Permission to use or copy this software for any purpose is hereby granted 9 * without fee, provided the above notices are retained on all copies. 10 * Permission to modify the code and to distribute modified code is granted, 11 * provided the above notices are retained, and a notice that the code was 12 * modified is included with the above copyright notice. 13 * 14 */ 15 16 /* NOTE: This is an internal header file, included by other STL headers. 17 * You should not attempt to use it directly. 18 */ 19 20 #ifndef _STLP_POINTERS_SPEC_TOOLS_H 21 #define _STLP_POINTERS_SPEC_TOOLS_H 22 23 #ifndef _STLP_TYPE_TRAITS_H 24 # include <stl/type_traits.h> 25 #endif 26 27 _STLP_BEGIN_NAMESPACE 28 29 //Some usefull declarations: 30 template <class _Tp> struct less; 31 32 _STLP_MOVE_TO_PRIV_NAMESPACE 33 34 template <class _StorageT, class _ValueT, class _BinaryPredicate> 35 struct _BinaryPredWrapper; 36 37 /* 38 * Since the compiler only allows at most one non-trivial 39 * implicit conversion we can make use of a shim class to 40 * be sure that functions below doesn't accept classes with 41 * implicit pointer conversion operators 42 */ 43 struct _VoidPointerShim 44 { _VoidPointerShim(void*); }; 45 struct _ConstVoidPointerShim 46 { _ConstVoidPointerShim(const void*); }; 47 struct _VolatileVoidPointerShim 48 { _VolatileVoidPointerShim(volatile void*); }; 49 struct _ConstVolatileVoidPointerShim 50 { _ConstVolatileVoidPointerShim(const volatile void*); }; 51 52 //The dispatch functions: 53 template <class _Tp> 54 char _UseVoidPtrStorageType(const __false_type& /*POD*/, const _Tp&); 55 char _UseVoidPtrStorageType(const __true_type& /*POD*/, ...); 56 char* _UseVoidPtrStorageType(const __true_type& /*POD*/, _VoidPointerShim); 57 58 template <class _Tp> 59 char _UseConstVoidPtrStorageType(const __false_type& /*POD*/, const _Tp&); 60 char _UseConstVoidPtrStorageType(const __true_type& /*POD*/, ...); 61 char* _UseConstVoidPtrStorageType(const __true_type& /*POD*/, _ConstVoidPointerShim); 62 63 template <class _Tp> 64 char _UseVolatileVoidPtrStorageType(const __false_type& /*POD*/, const _Tp&); 65 char _UseVolatileVoidPtrStorageType(const __true_type& /*POD*/, ...); 66 char* _UseVolatileVoidPtrStorageType(const __true_type& /*POD*/, _VolatileVoidPointerShim); 67 68 template <class _Tp> 69 char _UseConstVolatileVoidPtrStorageType(const __false_type& /*POD*/, const _Tp&); 70 char _UseConstVolatileVoidPtrStorageType(const __true_type& /*POD*/, ...); 71 char* _UseConstVolatileVoidPtrStorageType(const __true_type& /*POD*/, _ConstVolatileVoidPointerShim); 72 73 #if defined (_STLP_CLASS_PARTIAL_SPECIALIZATION) 74 /* Thanks to class partial specialization the pointer specialization feature can even be used in 75 * presence of incomplete type: 76 * struct MyStruct { 77 * typedef vector<MyStruct> MyStructContainer; 78 * typedef MyStructContainer::iterator MyStructIterator; 79 * }; 80 */ 81 82 template <class _Tp> 83 struct _StorageType { 84 typedef _Tp _QualifiedType; 85 typedef _Tp _Type; 86 enum { use_const_volatile_void_ptr = 0 }; 87 }; 88 89 template <class _Tp> 90 struct _StorageType<_Tp*> { 91 // Even if we detect a pointer type we use dispatch function to consider if it can be stored as a void*. 92 // For instance function pointer might not necessarily be convertible to void*. 93 enum { use_void_ptr = (sizeof(_UseVoidPtrStorageType(__true_type(), 94 __STATIC_CAST(_Tp*, 0))) == sizeof(char*)) }; 95 enum { use_const_volatile_void_ptr = use_void_ptr }; 96 typedef typename __select<use_void_ptr, 97 void*, 98 _Tp*>::_Ret _QualifiedType; 99 typedef _QualifiedType _Type; 100 }; 101 102 template <class _Tp> 103 struct _StorageType<_Tp const*> { 104 enum { use_void_ptr = (sizeof(_UseConstVoidPtrStorageType(__true_type(), 105 __STATIC_CAST(const _Tp*, 0))) == sizeof(char*)) }; 106 enum { use_const_volatile_void_ptr = use_void_ptr }; 107 typedef typename __select<use_void_ptr, 108 const void*, 109 const _Tp*>::_Ret _QualifiedType; 110 typedef typename __select<use_void_ptr, 111 void*, 112 const _Tp*>::_Ret _Type; 113 }; 114 115 template <class _Tp> 116 struct _StorageType<_Tp volatile*> { 117 enum { use_void_ptr = (sizeof(_UseVolatileVoidPtrStorageType(__true_type(), 118 __STATIC_CAST(_Tp volatile*, 0))) == sizeof(char*)) }; 119 enum { use_const_volatile_void_ptr = use_void_ptr }; 120 typedef typename __select<use_void_ptr, 121 volatile void*, 122 volatile _Tp*>::_Ret _QualifiedType; 123 typedef typename __select<use_void_ptr, 124 void*, 125 volatile _Tp*>::_Ret _Type; 126 }; 127 128 template <class _Tp> 129 struct _StorageType<_Tp const volatile*> { 130 enum { use_void_ptr = (sizeof(_UseConstVolatileVoidPtrStorageType(__true_type(), 131 __STATIC_CAST(_Tp const volatile*, 0))) == sizeof(char*)) }; 132 enum { use_const_volatile_void_ptr = use_void_ptr }; 133 typedef typename __select<use_void_ptr, 134 const volatile void*, 135 const volatile _Tp*>::_Ret _QualifiedType; 136 typedef typename __select<use_void_ptr, 137 void*, 138 const volatile _Tp*>::_Ret _Type; 139 }; 140 #else 141 template <class _Tp> 142 struct _StorageType { 143 typedef typename __type_traits<_Tp>::is_POD_type _PODType; 144 145 #if !defined (__BORLANDC__) || (__BORLANDC__ != 0x560) 146 static _Tp __null_rep(); 147 #else 148 static _Tp __null_rep; 149 #endif 150 enum { use_void_ptr = (sizeof(_UseVoidPtrStorageType(_PODType(), __null_rep())) == sizeof(char*)) }; 151 enum { use_const_void_ptr = (sizeof(_UseConstVoidPtrStorageType(_PODType(), __null_rep())) == sizeof(char*)) }; 152 enum { use_volatile_void_ptr = (sizeof(_UseVolatileVoidPtrStorageType(_PODType(), __null_rep())) == sizeof(char*)) }; 153 enum { use_const_volatile_void_ptr = (sizeof(_UseConstVolatileVoidPtrStorageType(_PODType(), __null_rep())) == sizeof(char*)) }; 154 155 typedef typename __select<!use_const_volatile_void_ptr, 156 _Tp, 157 typename __select<use_void_ptr, 158 void*, 159 typename __select<use_const_void_ptr, 160 const void*, 161 typename __select<use_volatile_void_ptr, 162 volatile void*, 163 const volatile void*>::_Ret >::_Ret >::_Ret >::_Ret _QualifiedType; 164 165 #if !defined (_STLP_CLASS_PARTIAL_SPECIALIZATION) 166 /* If the compiler do not support the iterator_traits structure we cannot wrap 167 * iterators pass to container template methods. The iterator dereferenced value 168 * has to be storable without any cast in the chosen storage type. To guaranty 169 * that the void pointer has to be correctly qualified. 170 */ 171 typedef _QualifiedType _Type; 172 #else 173 /* With iterator_traits we can wrap passed iterators and make the necessary casts. 174 * We can always use a simple void* storage type: 175 */ 176 typedef typename __select<use_const_volatile_void_ptr, 177 void*, 178 _Tp>::_Ret _Type; 179 #endif 180 }; 181 #endif 182 183 template <class _Tp, class _Compare> 184 struct _AssocStorageTypes { 185 typedef _StorageType<_Tp> _StorageTypeInfo; 186 typedef typename _StorageTypeInfo::_Type _SType; 187 188 //We need to also check that the comparison functor used to instanciate the assoc container 189 //is the default Standard less implementation: 190 enum { ptr_type = _StorageTypeInfo::use_const_volatile_void_ptr }; 191 typedef typename _IsSTLportClass<_Compare>::_Ret _STLportLess; 192 enum { is_default_less = __type2bool<_STLportLess>::_Ret }; 193 typedef typename __select<is_default_less, _SType, _Tp>::_Ret _KeyStorageType; 194 typedef typename __select<is_default_less && ptr_type, 195 _BinaryPredWrapper<_KeyStorageType, _Tp, _Compare>, 196 _Compare>::_Ret _CompareStorageType; 197 }; 198 199 200 #if defined (_STLP_CLASS_PARTIAL_SPECIALIZATION) 201 /* 202 * Base struct to deal with qualifiers 203 */ 204 template <class _StorageT, class _QualifiedStorageT> 205 struct _VoidCastTraitsAux { 206 typedef _QualifiedStorageT void_cv_type; 207 typedef _StorageT void_type; 208 209 static void_type * uncv_ptr(void_cv_type *__ptr) 210 { return __ptr; } 211 static void_type const* uncv_cptr(void_cv_type const*__ptr) 212 { return __ptr; } 213 static void_type ** uncv_pptr(void_cv_type **__ptr) 214 { return __ptr; } 215 static void_type & uncv_ref(void_cv_type & __ref) 216 { return __ref; } 217 static void_type const& uncv_cref(void_cv_type const& __ref) 218 { return __ref; } 219 static void_cv_type* cv_ptr(void_type *__ptr) 220 { return __ptr; } 221 static void_cv_type const* cv_cptr(void_type const*__ptr) 222 { return __ptr; } 223 static void_cv_type ** cv_pptr(void_type **__ptr) 224 { return __ptr; } 225 static void_cv_type & cv_ref(void_type & __ref) 226 { return __ref; } 227 static void_cv_type const& cv_cref(void_type const& __ref) 228 { return __ref; } 229 }; 230 231 template <class _VoidCVType> 232 struct _VoidCastTraitsAuxBase { 233 typedef _VoidCVType* void_cv_type; 234 typedef void* void_type; 235 236 static void_type* uncv_ptr(void_cv_type *__ptr) 237 { return __CONST_CAST(void_type*, __ptr); } 238 static void_type const* uncv_cptr(void_cv_type const*__ptr) 239 { return __CONST_CAST(void_type const*, __ptr); } 240 static void_type** uncv_pptr(void_cv_type **__ptr) 241 { return __CONST_CAST(void_type**, __ptr); } 242 static void_type& uncv_ref(void_cv_type &__ref) 243 { return __CONST_CAST(void_type&, __ref); } 244 static void_type const& uncv_cref(void_cv_type const& __ptr) 245 { return __CONST_CAST(void_type const&, __ptr); } 246 // The reverse versions 247 static void_cv_type * cv_ptr(void_type *__ptr) 248 { return __CONST_CAST(void_cv_type *, __ptr); } 249 static void_cv_type const* cv_cptr(void_type const*__ptr) 250 { return __CONST_CAST(void_cv_type const*, __ptr); } 251 static void_cv_type ** cv_pptr(void_type **__ptr) 252 { return __CONST_CAST(void_cv_type**, __ptr); } 253 static void_cv_type & cv_ref(void_type &__ref) 254 { return __CONST_CAST(void_cv_type &, __ref); } 255 static void_cv_type const& cv_cref(void_type const& __ref) 256 { return __CONST_CAST(void_cv_type const&, __ref); } 257 }; 258 259 _STLP_TEMPLATE_NULL 260 struct _VoidCastTraitsAux<void*, const void*> : _VoidCastTraitsAuxBase<void const> 261 {}; 262 _STLP_TEMPLATE_NULL 263 struct _VoidCastTraitsAux<void*, volatile void*> : _VoidCastTraitsAuxBase<void volatile> 264 {}; 265 _STLP_TEMPLATE_NULL 266 struct _VoidCastTraitsAux<void*, const volatile void*> : _VoidCastTraitsAuxBase<void const volatile> 267 {}; 268 269 template <class _StorageT, class _ValueT> 270 struct _CastTraits { 271 typedef _ValueT value_type; 272 typedef typename _StorageType<_ValueT>::_QualifiedType _QualifiedStorageT; 273 typedef _VoidCastTraitsAux<_StorageT, _QualifiedStorageT> cv_traits; 274 typedef typename cv_traits::void_type void_type; 275 typedef typename cv_traits::void_cv_type void_cv_type; 276 277 static value_type * to_value_type_ptr(void_type *__ptr) 278 { return __REINTERPRET_CAST(value_type *, cv_traits::cv_ptr(__ptr)); } 279 static value_type const* to_value_type_cptr(void_type const*__ptr) 280 { return __REINTERPRET_CAST(value_type const*, cv_traits::cv_cptr(__ptr)); } 281 static value_type ** to_value_type_pptr(void_type **__ptr) 282 { return __REINTERPRET_CAST(value_type **, cv_traits::cv_pptr(__ptr)); } 283 static value_type & to_value_type_ref(void_type &__ref) 284 { return __REINTERPRET_CAST(value_type &, cv_traits::cv_ref(__ref)); } 285 static value_type const& to_value_type_cref(void_type const& __ptr) 286 { return __REINTERPRET_CAST(value_type const&, cv_traits::cv_cref(__ptr)); } 287 // Reverse versions 288 static void_type * to_storage_type_ptr(value_type *__ptr) 289 { return cv_traits::uncv_ptr(__REINTERPRET_CAST(void_cv_type *, __ptr)); } 290 static void_type const* to_storage_type_cptr(value_type const*__ptr) 291 { return cv_traits::uncv_cptr(__REINTERPRET_CAST(void_cv_type const*, __ptr)); } 292 static void_type ** to_storage_type_pptr(value_type **__ptr) 293 { return cv_traits::uncv_pptr(__REINTERPRET_CAST(void_cv_type **, __ptr)); } 294 static void_type const& to_storage_type_cref(value_type const& __ref) 295 { return cv_traits::uncv_cref(__REINTERPRET_CAST(void_cv_type const&, __ref)); } 296 297 //Method used to treat set container template method extension 298 static void_type const& to_storage_type_crefT(value_type const& __ref) 299 { return to_storage_type_cref(__ref); } 300 }; 301 302 template <class _Tp> 303 struct _CastTraits<_Tp, _Tp> { 304 typedef _Tp storage_type; 305 typedef _Tp value_type; 306 307 static value_type * to_value_type_ptr(storage_type *__ptr) 308 { return __ptr; } 309 static value_type const* to_value_type_cptr(storage_type const*__ptr) 310 { return __ptr; } 311 static value_type ** to_value_type_pptr(storage_type **__ptr) 312 { return __ptr; } 313 static value_type & to_value_type_ref(storage_type &__ref) 314 { return __ref; } 315 static value_type const& to_value_type_cref(storage_type const&__ref) 316 { return __ref; } 317 // Reverse versions 318 static storage_type * to_storage_type_ptr(value_type *__ptr) 319 { return __ptr; } 320 static storage_type const* to_storage_type_cptr(value_type const*__ptr) 321 { return __ptr; } 322 static storage_type ** to_storage_type_pptr(value_type **__ptr) 323 { return __ptr; } 324 static storage_type const& to_storage_type_cref(value_type const& __ref) 325 { return __ref; } 326 327 //Method used to treat set container template method extension 328 template <class _Tp1> 329 static _Tp1 const& to_storage_type_crefT(_Tp1 const& __ref) 330 { return __ref; } 331 }; 332 333 #define _STLP_USE_ITERATOR_WRAPPER 334 335 template <class _StorageT, class _ValueT, class _Iterator> 336 struct _IteWrapper { 337 typedef _CastTraits<_StorageT, _ValueT> cast_traits; 338 typedef iterator_traits<_Iterator> _IteTraits; 339 340 typedef typename _IteTraits::iterator_category iterator_category; 341 typedef _StorageT value_type; 342 typedef typename _IteTraits::difference_type difference_type; 343 typedef value_type* pointer; 344 typedef value_type const& const_reference; 345 //This wrapper won't be used for input so to avoid surprise 346 //the reference type will be a const reference: 347 typedef const_reference reference; 348 349 typedef _IteWrapper<_StorageT, _ValueT, _Iterator> _Self; 350 typedef _Self _Ite; 351 352 _IteWrapper(_Iterator &__ite) : _M_ite(__ite) {} 353 354 const_reference operator*() const { return cast_traits::to_storage_type_cref(*_M_ite); } 355 356 _Self& operator= (_Self const& __rhs) { 357 _M_ite = __rhs._M_ite; 358 return *this; 359 } 360 361 _Self& operator++() { 362 ++_M_ite; 363 return *this; 364 } 365 366 _Self& operator--() { 367 --_M_ite; 368 return *this; 369 } 370 371 _Self& operator += (difference_type __offset) { 372 _M_ite += __offset; 373 return *this; 374 } 375 difference_type operator -(_Self const& __other) const 376 { return _M_ite - __other._M_ite; } 377 378 bool operator == (_Self const& __other) const 379 { return _M_ite == __other._M_ite; } 380 381 bool operator != (_Self const& __other) const 382 { return _M_ite != __other._M_ite; } 383 384 bool operator < (_Self const& __rhs) const 385 { return _M_ite < __rhs._M_ite; } 386 387 private: 388 _Iterator _M_ite; 389 }; 390 391 template <class _Tp, class _Iterator> 392 struct _IteWrapper<_Tp, _Tp, _Iterator> 393 { typedef _Iterator _Ite; }; 394 395 #else 396 397 /* 398 * In this config the storage type is qualified in respect of the 399 * value_type qualification. Simple reinterpret_cast is enough. 400 */ 401 template <class _StorageT, class _ValueT> 402 struct _CastTraits { 403 typedef _StorageT storage_type; 404 typedef _ValueT value_type; 405 406 static value_type * to_value_type_ptr(storage_type *__ptr) 407 { return __REINTERPRET_CAST(value_type*, __ptr); } 408 static value_type const* to_value_type_cptr(storage_type const*__ptr) 409 { return __REINTERPRET_CAST(value_type const*, __ptr); } 410 static value_type ** to_value_type_pptr(storage_type **__ptr) 411 { return __REINTERPRET_CAST(value_type **, __ptr); } 412 static value_type & to_value_type_ref(storage_type &__ref) 413 { return __REINTERPRET_CAST(value_type&, __ref); } 414 static value_type const& to_value_type_cref(storage_type const&__ref) 415 { return __REINTERPRET_CAST(value_type const&, __ref); } 416 // Reverse versions 417 static storage_type * to_storage_type_ptr(value_type *__ptr) 418 { return __REINTERPRET_CAST(storage_type*, __ptr); } 419 static storage_type const* to_storage_type_cptr(value_type const*__ptr) 420 { return __REINTERPRET_CAST(storage_type const*, __ptr); } 421 static storage_type ** to_storage_type_pptr(value_type **__ptr) 422 { return __REINTERPRET_CAST(storage_type **, __ptr); } 423 static storage_type const& to_storage_type_cref(value_type const&__ref) 424 { return __REINTERPRET_CAST(storage_type const&, __ref); } 425 template <class _Tp1> 426 static _Tp1 const& to_storage_type_crefT(_Tp1 const& __ref) 427 { return __ref; } 428 }; 429 430 #endif 431 432 //Wrapper functors: 433 template <class _StorageT, class _ValueT, class _UnaryPredicate> 434 struct _UnaryPredWrapper { 435 typedef _CastTraits<_StorageT, _ValueT> cast_traits; 436 437 _UnaryPredWrapper (_UnaryPredicate const& __pred) : _M_pred(__pred) {} 438 439 bool operator () (_StorageT const& __ref) const 440 { return _M_pred(cast_traits::to_value_type_cref(__ref)); } 441 442 private: 443 _UnaryPredicate _M_pred; 444 }; 445 446 template <class _StorageT, class _ValueT, class _BinaryPredicate> 447 struct _BinaryPredWrapper { 448 typedef _CastTraits<_StorageT, _ValueT> cast_traits; 449 450 _BinaryPredWrapper () {} 451 _BinaryPredWrapper (_BinaryPredicate const& __pred) : _M_pred(__pred) {} 452 453 _BinaryPredicate get_pred() const { return _M_pred; } 454 455 bool operator () (_StorageT const& __fst, _StorageT const& __snd) const 456 { return _M_pred(cast_traits::to_value_type_cref(__fst), cast_traits::to_value_type_cref(__snd)); } 457 458 //Cast operator used to transparently access underlying predicate 459 //in set::key_comp() method 460 operator _BinaryPredicate() const 461 { return _M_pred; } 462 463 private: 464 _BinaryPredicate _M_pred; 465 }; 466 467 _STLP_MOVE_TO_STD_NAMESPACE 468 469 _STLP_END_NAMESPACE 470 471 #endif /* _STLP_POINTERS_SPEC_TOOLS_H */ 472