_tools.h 18 KB

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