/src/Util/detail/any_iterator_metafunctions.hpp

https://github.com/iaefai/Spider-Fish · C++ Header · 363 lines · 250 code · 31 blank · 82 comment · 0 complexity · b79b4b46d7a0ca0c1535f47b54339af7 MD5 · raw file

  1. // (C) Copyright Thomas Becker 2005. Permission to copy, use, modify, sell and
  2. // distribute this software is granted provided this copyright notice appears
  3. // in all copies. This software is provided "as is" without express or implied
  4. // warranty, and with no claim as to its suitability for any purpose.
  5. // File Name
  6. // =========
  7. //
  8. // metafunctions.h
  9. // Description
  10. // ===========
  11. //
  12. // Metafunctions for any_iterator
  13. #ifndef ANY_ITERATOR_METAFUNCTIONS_01102007TMB_HPP
  14. #define ANY_ITERATOR_METAFUNCTIONS_01102007TMB_HPP
  15. // Revision History
  16. // ================
  17. //
  18. // 27 Dec 2006 (Thomas Becker) Created
  19. // Includes
  20. // ========
  21. #include <boost/iterator/iterator_categories.hpp>
  22. #include <boost/iterator/iterator_traits.hpp>
  23. #include <boost/type_traits/remove_const.hpp>
  24. #include <boost/type_traits/remove_reference.hpp>
  25. #include <boost/type_traits/is_same.hpp>
  26. #include <boost/type_traits/is_base_of.hpp>
  27. #include <boost/type_traits/is_convertible.hpp>
  28. #include <boost/type_traits/is_reference.hpp>
  29. #include <boost/type_traits/is_pointer.hpp>
  30. #include <boost/mpl/bool.hpp>
  31. #include <boost/mpl/and.hpp>
  32. #include <boost/mpl/or.hpp>
  33. #include <boost/mpl/not.hpp>
  34. namespace IteratorTypeErasure
  35. {
  36. template<
  37. class Value,
  38. class Traversal,
  39. class Reference,
  40. class Difference
  41. >
  42. class any_iterator;
  43. namespace detail
  44. {
  45. ///////////////////////////////////////////////////////////////////////
  46. //
  47. template<typename T>
  48. struct remove_reference_and_const
  49. {
  50. typedef typename boost::remove_const<
  51. typename boost::remove_reference<
  52. typename boost::remove_const<
  53. T
  54. >::type
  55. >::type
  56. >::type type;
  57. };
  58. ///////////////////////////////////////////////////////////////////////
  59. //
  60. template<typename IteratorReference>
  61. struct make_iterator_reference_const
  62. {
  63. typedef typename boost::mpl::if_<
  64. typename boost::is_reference<IteratorReference>::type,
  65. typename boost::remove_const<
  66. typename boost::remove_reference<
  67. typename boost::remove_const<
  68. IteratorReference
  69. >::type
  70. >::type
  71. >::type const &,
  72. typename boost::remove_const<
  73. typename boost::remove_reference<
  74. typename boost::remove_const<
  75. IteratorReference
  76. >::type
  77. >::type
  78. >::type const
  79. >::type type;
  80. };
  81. ///////////////////////////////////////////////////////////////////////
  82. //
  83. template<
  84. class WrappedIterator,
  85. class AnyIterator
  86. >
  87. struct value_types_erasure_compatible
  88. {
  89. // Really, we just want WrappedIterator's value_type to convert to
  90. // AnyIterator's value_type. But many real world output iterators
  91. // define their value_type as void. Therefore, we simply ignore
  92. // the value type for output iterators. That's fine because for
  93. // output iterators, the relevant type erasure information is all
  94. // in the reference type.
  95. typedef typename boost::mpl::or_<
  96. boost::is_same<
  97. typename boost::iterator_category<WrappedIterator>::type,
  98. std::output_iterator_tag
  99. >,
  100. // Really, we just want WrappedIterator's value_type to convert to
  101. // AnyIterator's value_type. But we need to work around a flaw in
  102. // boost::is_convertible. boost::is_convertible<X, Y>::value is
  103. // false whenever X and Y are abstract base classes (even when X
  104. // and Y are the same). This will be fixed in C++ concepts.
  105. boost::mpl::or_<
  106. boost::is_same<
  107. typename boost::iterator_value<WrappedIterator>::type,
  108. typename boost::iterator_value<AnyIterator>::type
  109. >,
  110. boost::is_base_of<
  111. typename boost::iterator_value<AnyIterator>::type,
  112. typename boost::iterator_value<WrappedIterator>::type
  113. >,
  114. boost::is_convertible<
  115. typename boost::iterator_value<WrappedIterator>::type,
  116. typename boost::iterator_value<AnyIterator>::type
  117. >
  118. >
  119. > type;
  120. };
  121. ///////////////////////////////////////////////////////////////////////
  122. //
  123. template<
  124. class WrappedIterator,
  125. class AnyIterator
  126. >
  127. struct reference_types_erasure_compatible_1
  128. {
  129. typedef typename boost::is_convertible<
  130. typename boost::iterator_reference<WrappedIterator>::type,
  131. typename boost::iterator_reference<AnyIterator>::type
  132. >::type type;
  133. };
  134. ///////////////////////////////////////////////////////////////////////
  135. //
  136. template<
  137. class WrappedIterator,
  138. class AnyIterator
  139. >
  140. struct reference_types_erasure_compatible_2
  141. {
  142. typedef typename boost::mpl::if_<
  143. boost::is_reference<
  144. typename boost::iterator_reference<AnyIterator>::type
  145. >,
  146. boost::is_reference<
  147. typename boost::iterator_reference<WrappedIterator>::type
  148. >,
  149. boost::mpl::bool_<true>
  150. >::type type;
  151. };
  152. ///////////////////////////////////////////////////////////////////////
  153. //
  154. template<
  155. class WrappedIterator,
  156. class AnyIterator
  157. >
  158. struct reference_types_erasure_compatible_3
  159. {
  160. typedef typename boost::mpl::if_<
  161. boost::mpl::and_<
  162. boost::is_reference<
  163. typename boost::iterator_reference<AnyIterator>::type
  164. >,
  165. boost::is_reference<
  166. typename boost::iterator_reference<WrappedIterator>::type
  167. >
  168. >,
  169. boost::mpl::or_<
  170. boost::is_same<
  171. typename remove_reference_and_const<
  172. typename boost::iterator_reference<AnyIterator>::type
  173. >::type,
  174. typename remove_reference_and_const<
  175. typename boost::iterator_reference<WrappedIterator>::type
  176. >::type
  177. >,
  178. boost::is_base_of<
  179. typename remove_reference_and_const<
  180. typename boost::iterator_reference<AnyIterator>::type
  181. >::type,
  182. typename remove_reference_and_const<
  183. typename boost::iterator_reference<WrappedIterator>::type
  184. >::type
  185. >
  186. >,
  187. boost::mpl::bool_<true>
  188. >::type type;
  189. };
  190. ///////////////////////////////////////////////////////////////////////
  191. //
  192. template<
  193. class WrappedIterator,
  194. class AnyIterator
  195. >
  196. struct reference_types_erasure_compatible
  197. {
  198. // Output iterators are weird. Many real world output iterators
  199. // define their reference type as void. In the world of boost
  200. // iterators, that's terribly wrong, because in that world, an
  201. // iterator's reference type is always the result type of
  202. // operator* (and that makes very good sense, too). Therefore,
  203. // when WrappedIterator is an output iterator, we use
  204. // WrappedIterator& for WrappedIterator's reference type,
  205. // because that's the real, true reference type. Moreover,
  206. // we just require that WrappedIterator& convert to AnyIterator's
  207. // reference type. The other subtleties are not relevant.
  208. typedef typename boost::mpl::if_<
  209. boost::is_same<
  210. typename boost::iterator_category<WrappedIterator>::type,
  211. std::output_iterator_tag
  212. >,
  213. boost::is_convertible<
  214. WrappedIterator&,
  215. typename boost::iterator_reference<AnyIterator>::type
  216. >,
  217. boost::mpl::and_<
  218. // WrappedIterator's reference type must convert to AnyIterator's reference type.
  219. typename reference_types_erasure_compatible_1<WrappedIterator, AnyIterator>::type,
  220. // If AnyIterator's reference type is a reference, then the
  221. // same must be true for WrappedIterator's reference type.
  222. typename reference_types_erasure_compatible_2<WrappedIterator, AnyIterator>::type,
  223. // If AnyIterator's reference type and WrappedIterator's
  224. // reference type are both references, then one of the
  225. // following must hold:
  226. //
  227. // 1) AnyIterator's reference type and WrappedIterator's
  228. // reference type are the same.
  229. //
  230. // 2) AnyIterator's reference type is a base class of WrappedIterator's
  231. // reference type.
  232. //
  233. typename reference_types_erasure_compatible_3<WrappedIterator, AnyIterator>::type
  234. >
  235. >::type type;
  236. };
  237. ///////////////////////////////////////////////////////////////////////
  238. //
  239. template<
  240. class WrappedIterator,
  241. class AnyIterator
  242. >
  243. struct difference_types_erasure_compatible
  244. {
  245. // Difference type matters only for random access iterators.
  246. typedef typename boost::mpl::or_<
  247. boost::mpl::not_<
  248. boost::is_same<
  249. // Do not use boost::iterator_traversal<AnyIterator>::type here,
  250. // as it does not equal the traversal tag.
  251. typename AnyIterator::Traversal,
  252. boost::random_access_traversal_tag
  253. >
  254. >,
  255. boost::mpl::and_<
  256. boost::is_convertible<
  257. typename boost::iterator_difference<WrappedIterator>::type,
  258. typename boost::iterator_difference<AnyIterator>::type
  259. >,
  260. boost::is_convertible<
  261. typename boost::iterator_difference<AnyIterator>::type,
  262. typename boost::iterator_difference<WrappedIterator>::type
  263. >
  264. >
  265. > type;
  266. };
  267. ///////////////////////////////////////////////////////////////////////
  268. //
  269. template<
  270. class WrappedIterator,
  271. class AnyIterator
  272. >
  273. struct traversal_types_erasure_compatible
  274. {
  275. typedef typename boost::mpl::or_<
  276. boost::is_same<
  277. // Do not use boost::iterator_traversal<AnyIterator>::type here,
  278. // as it does not equal the traversal tag.
  279. typename AnyIterator::Traversal,
  280. typename boost::iterator_traversal<WrappedIterator>::type
  281. >,
  282. boost::is_base_of<
  283. // Do not use boost::iterator_traversal<AnyIterator>::type here,
  284. // as it does not equal the traversal tag.
  285. typename AnyIterator::Traversal,
  286. typename boost::iterator_traversal<WrappedIterator>::type
  287. >
  288. > type;
  289. };
  290. ///////////////////////////////////////////////////////////////////////
  291. //
  292. template<
  293. class WrappedIterator,
  294. class AnyIterator
  295. >
  296. struct is_iterator_type_erasure_compatible :
  297. public boost::mpl::bool_<
  298. boost::mpl::and_<
  299. value_types_erasure_compatible<WrappedIterator, AnyIterator>,
  300. reference_types_erasure_compatible<WrappedIterator, AnyIterator>,
  301. difference_types_erasure_compatible<WrappedIterator, AnyIterator>,
  302. traversal_types_erasure_compatible<WrappedIterator, AnyIterator>
  303. >::value
  304. >
  305. {
  306. };
  307. ///////////////////////////////////////////////////////////////////////
  308. //
  309. template<class SomeIterator>
  310. struct is_any_iterator : public boost::mpl::bool_<false>
  311. {
  312. };
  313. //
  314. template<
  315. class Value,
  316. class Traversal,
  317. class Reference,
  318. class Difference
  319. >
  320. struct is_any_iterator<
  321. any_iterator<
  322. Value,
  323. Traversal,
  324. Reference,
  325. Difference
  326. >
  327. > : public boost::mpl::bool_<true>
  328. {
  329. };
  330. } // end namespace detail
  331. } // end namespace IteratorTypeErasure
  332. #endif // ANY_ITERATOR_METAFUNCTIONS_01102007TMB_HPP