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: 30template <class _Tp> struct less; 31 32_STLP_MOVE_TO_PRIV_NAMESPACE 33 34template <class _StorageT, class _ValueT, class _BinaryPredicate> 35struct _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 */ 43struct _VoidPointerShim 44{ _VoidPointerShim(void*); }; 45struct _ConstVoidPointerShim 46{ _ConstVoidPointerShim(const void*); }; 47struct _VolatileVoidPointerShim 48{ _VolatileVoidPointerShim(volatile void*); }; 49struct _ConstVolatileVoidPointerShim 50{ _ConstVolatileVoidPointerShim(const volatile void*); }; 51 52//The dispatch functions: 53template <class _Tp> 54char _UseVoidPtrStorageType(const __false_type& /*POD*/, const _Tp&); 55char _UseVoidPtrStorageType(const __true_type& /*POD*/, ...); 56char* _UseVoidPtrStorageType(const __true_type& /*POD*/, _VoidPointerShim); 57 58template <class _Tp> 59char _UseConstVoidPtrStorageType(const __false_type& /*POD*/, const _Tp&); 60char _UseConstVoidPtrStorageType(const __true_type& /*POD*/, ...); 61char* _UseConstVoidPtrStorageType(const __true_type& /*POD*/, _ConstVoidPointerShim); 62 63template <class _Tp> 64char _UseVolatileVoidPtrStorageType(const __false_type& /*POD*/, const _Tp&); 65char _UseVolatileVoidPtrStorageType(const __true_type& /*POD*/, ...); 66char* _UseVolatileVoidPtrStorageType(const __true_type& /*POD*/, _VolatileVoidPointerShim); 67 68template <class _Tp> 69char _UseConstVolatileVoidPtrStorageType(const __false_type& /*POD*/, const _Tp&); 70char _UseConstVolatileVoidPtrStorageType(const __true_type& /*POD*/, ...); 71char* _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 82template <class _Tp> 83struct _StorageType { 84 typedef _Tp _QualifiedType; 85 typedef _Tp _Type; 86 enum { use_const_volatile_void_ptr = 0 }; 87}; 88 89template <class _Tp> 90struct _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 102template <class _Tp> 103struct _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 115template <class _Tp> 116struct _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 128template <class _Tp> 129struct _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 141template <class _Tp> 142struct _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 183template <class _Tp, class _Compare> 184struct _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 */ 204template <class _StorageT, class _QualifiedStorageT> 205struct _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 231template <class _VoidCVType> 232struct _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 260struct _VoidCastTraitsAux<void*, const void*> : _VoidCastTraitsAuxBase<void const> 261{}; 262_STLP_TEMPLATE_NULL 263struct _VoidCastTraitsAux<void*, volatile void*> : _VoidCastTraitsAuxBase<void volatile> 264{}; 265_STLP_TEMPLATE_NULL 266struct _VoidCastTraitsAux<void*, const volatile void*> : _VoidCastTraitsAuxBase<void const volatile> 267{}; 268 269template <class _StorageT, class _ValueT> 270struct _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 302template <class _Tp> 303struct _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 335template <class _StorageT, class _ValueT, class _Iterator> 336struct _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 387private: 388 _Iterator _M_ite; 389}; 390 391template <class _Tp, class _Iterator> 392struct _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 */ 401template <class _StorageT, class _ValueT> 402struct _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: 433template <class _StorageT, class _ValueT, class _UnaryPredicate> 434struct _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 442private: 443 _UnaryPredicate _M_pred; 444}; 445 446template <class _StorageT, class _ValueT, class _BinaryPredicate> 447struct _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 463private: 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