facade_iterator_category.hpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. // Copyright David Abrahams 2003. Use, modification and distribution is
  2. // subject to the Boost Software License, Version 1.0. (See accompanying
  3. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  4. #ifndef FACADE_ITERATOR_CATEGORY_DWA20031118_HPP
  5. # define FACADE_ITERATOR_CATEGORY_DWA20031118_HPP
  6. # include <boost/core/use_default.hpp>
  7. # include <boost/iterator/iterator_categories.hpp>
  8. # include <boost/mpl/or.hpp> // used in iterator_tag inheritance logic
  9. # include <boost/mpl/and.hpp>
  10. # include <boost/mpl/if.hpp>
  11. # include <boost/mpl/eval_if.hpp>
  12. # include <boost/mpl/identity.hpp>
  13. # include <boost/mpl/assert.hpp>
  14. # include <boost/type_traits/is_same.hpp>
  15. # include <boost/type_traits/is_const.hpp>
  16. # include <boost/type_traits/is_reference.hpp>
  17. # include <boost/type_traits/is_convertible.hpp>
  18. # include <boost/type_traits/is_same.hpp>
  19. # include <boost/iterator/detail/config_def.hpp> // try to keep this last
  20. # ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
  21. # include <boost/detail/indirect_traits.hpp>
  22. # endif
  23. //
  24. // iterator_category deduction for iterator_facade
  25. //
  26. namespace boost {
  27. namespace iterators {
  28. using boost::use_default;
  29. namespace detail {
  30. struct input_output_iterator_tag
  31. : std::input_iterator_tag
  32. {
  33. // Using inheritance for only input_iterator_tag helps to avoid
  34. // ambiguities when a stdlib implementation dispatches on a
  35. // function which is overloaded on both input_iterator_tag and
  36. // output_iterator_tag, as STLPort does, in its __valid_range
  37. // function. I claim it's better to avoid the ambiguity in these
  38. // cases.
  39. operator std::output_iterator_tag() const
  40. {
  41. return std::output_iterator_tag();
  42. }
  43. };
  44. //
  45. // True iff the user has explicitly disabled writability of this
  46. // iterator. Pass the iterator_facade's Value parameter and its
  47. // nested ::reference type.
  48. //
  49. template <class ValueParam, class Reference>
  50. struct iterator_writability_disabled
  51. # ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY // Adding Thomas' logic?
  52. : mpl::or_<
  53. is_const<Reference>
  54. , boost::detail::indirect_traits::is_reference_to_const<Reference>
  55. , is_const<ValueParam>
  56. >
  57. # else
  58. : is_const<ValueParam>
  59. # endif
  60. {};
  61. //
  62. // Convert an iterator_facade's traversal category, Value parameter,
  63. // and ::reference type to an appropriate old-style category.
  64. //
  65. // Due to changeset 21683, this now never results in a category convertible
  66. // to output_iterator_tag.
  67. //
  68. // Change at: https://svn.boost.org/trac/boost/changeset/21683
  69. template <class Traversal, class ValueParam, class Reference>
  70. struct iterator_facade_default_category
  71. : mpl::eval_if<
  72. mpl::and_<
  73. is_reference<Reference>
  74. , is_convertible<Traversal,forward_traversal_tag>
  75. >
  76. , mpl::eval_if<
  77. is_convertible<Traversal,random_access_traversal_tag>
  78. , mpl::identity<std::random_access_iterator_tag>
  79. , mpl::if_<
  80. is_convertible<Traversal,bidirectional_traversal_tag>
  81. , std::bidirectional_iterator_tag
  82. , std::forward_iterator_tag
  83. >
  84. >
  85. , typename mpl::eval_if<
  86. mpl::and_<
  87. is_convertible<Traversal, single_pass_traversal_tag>
  88. // check for readability
  89. , is_convertible<Reference, ValueParam>
  90. >
  91. , mpl::identity<std::input_iterator_tag>
  92. , mpl::identity<Traversal>
  93. >
  94. >
  95. {
  96. };
  97. // True iff T is convertible to an old-style iterator category.
  98. template <class T>
  99. struct is_iterator_category
  100. : mpl::or_<
  101. is_convertible<T,std::input_iterator_tag>
  102. , is_convertible<T,std::output_iterator_tag>
  103. >
  104. {
  105. };
  106. template <class T>
  107. struct is_iterator_traversal
  108. : is_convertible<T,incrementable_traversal_tag>
  109. {};
  110. //
  111. // A composite iterator_category tag convertible to Category (a pure
  112. // old-style category) and Traversal (a pure traversal tag).
  113. // Traversal must be a strict increase of the traversal power given by
  114. // Category.
  115. //
  116. template <class Category, class Traversal>
  117. struct iterator_category_with_traversal
  118. : Category, Traversal
  119. {
  120. // Make sure this isn't used to build any categories where
  121. // convertibility to Traversal is redundant. Should just use the
  122. // Category element in that case.
  123. BOOST_MPL_ASSERT_NOT((
  124. is_convertible<
  125. typename iterator_category_to_traversal<Category>::type
  126. , Traversal
  127. >));
  128. BOOST_MPL_ASSERT((is_iterator_category<Category>));
  129. BOOST_MPL_ASSERT_NOT((is_iterator_category<Traversal>));
  130. BOOST_MPL_ASSERT_NOT((is_iterator_traversal<Category>));
  131. # if !BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310))
  132. BOOST_MPL_ASSERT((is_iterator_traversal<Traversal>));
  133. # endif
  134. };
  135. // Computes an iterator_category tag whose traversal is Traversal and
  136. // which is appropriate for an iterator
  137. template <class Traversal, class ValueParam, class Reference>
  138. struct facade_iterator_category_impl
  139. {
  140. BOOST_MPL_ASSERT_NOT((is_iterator_category<Traversal>));
  141. typedef typename iterator_facade_default_category<
  142. Traversal,ValueParam,Reference
  143. >::type category;
  144. typedef typename mpl::if_<
  145. is_same<
  146. Traversal
  147. , typename iterator_category_to_traversal<category>::type
  148. >
  149. , category
  150. , iterator_category_with_traversal<category,Traversal>
  151. >::type type;
  152. };
  153. //
  154. // Compute an iterator_category for iterator_facade
  155. //
  156. template <class CategoryOrTraversal, class ValueParam, class Reference>
  157. struct facade_iterator_category
  158. : mpl::eval_if<
  159. is_iterator_category<CategoryOrTraversal>
  160. , mpl::identity<CategoryOrTraversal> // old-style categories are fine as-is
  161. , facade_iterator_category_impl<CategoryOrTraversal,ValueParam,Reference>
  162. >
  163. {
  164. };
  165. }}} // namespace boost::iterators::detail
  166. # include <boost/iterator/detail/config_undef.hpp>
  167. #endif // FACADE_ITERATOR_CATEGORY_DWA20031118_HPP