transform_iterator.hpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // (C) Copyright David Abrahams 2002.
  2. // (C) Copyright Jeremy Siek 2002.
  3. // (C) Copyright Thomas Witt 2002.
  4. // Distributed under the Boost Software License, Version 1.0. (See
  5. // accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_ITERATOR_TRANSFORM_ITERATOR_23022003THW_HPP
  8. #define BOOST_ITERATOR_TRANSFORM_ITERATOR_23022003THW_HPP
  9. #include <iterator>
  10. #include <type_traits>
  11. #include <boost/core/use_default.hpp>
  12. #include <boost/core/empty_value.hpp>
  13. #include <boost/iterator/iterator_adaptor.hpp>
  14. #include <boost/iterator/enable_if_convertible.hpp>
  15. #include <boost/iterator/detail/eval_if_default.hpp>
  16. namespace boost {
  17. namespace iterators {
  18. template<
  19. typename UnaryFunction,
  20. typename Iterator,
  21. typename Reference = use_default,
  22. typename Value = use_default
  23. >
  24. class transform_iterator;
  25. namespace detail {
  26. template< typename UnaryFunc, typename Iterator >
  27. struct transform_iterator_default_reference
  28. {
  29. using type = decltype(std::declval< UnaryFunc const& >()(std::declval< typename std::iterator_traits< Iterator >::reference >()));
  30. };
  31. // Compute the iterator_adaptor instantiation to be used for transform_iterator
  32. template< typename UnaryFunc, typename Iterator, typename Reference, typename Value >
  33. struct transform_iterator_base
  34. {
  35. private:
  36. // By default, dereferencing the iterator yields the same as
  37. // the function.
  38. using reference = detail::eval_if_default_t<
  39. Reference,
  40. transform_iterator_default_reference< UnaryFunc, Iterator >
  41. >;
  42. // To get the default for Value: remove any reference on the
  43. // result type, but retain any constness to signal
  44. // non-writability. Note that if we adopt Thomas' suggestion
  45. // to key non-writability *only* on the Reference argument,
  46. // we'd need to strip constness here as well.
  47. using cv_value_type = detail::eval_if_default_t<
  48. Value,
  49. std::remove_reference< reference >
  50. >;
  51. public:
  52. using type = iterator_adaptor<
  53. transform_iterator< UnaryFunc, Iterator, Reference, Value >,
  54. Iterator,
  55. cv_value_type,
  56. use_default, // Leave the traversal category alone
  57. reference
  58. >;
  59. };
  60. } // namespace detail
  61. template< typename UnaryFunc, typename Iterator, typename Reference, typename Value >
  62. class transform_iterator :
  63. public detail::transform_iterator_base< UnaryFunc, Iterator, Reference, Value >::type,
  64. private boost::empty_value< UnaryFunc >
  65. {
  66. friend class iterator_core_access;
  67. private:
  68. using super_t = typename detail::transform_iterator_base< UnaryFunc, Iterator, Reference, Value >::type;
  69. using functor_base = boost::empty_value< UnaryFunc >;
  70. public:
  71. transform_iterator() = default;
  72. transform_iterator(Iterator const& x, UnaryFunc f) :
  73. super_t(x),
  74. functor_base(boost::empty_init_t{}, f)
  75. {}
  76. // don't provide this constructor if UnaryFunc is a
  77. // function pointer type, since it will be 0. Too dangerous.
  78. template< bool Requires = std::is_class< UnaryFunc >::value, typename = typename std::enable_if< Requires >::type >
  79. explicit transform_iterator(Iterator const& x) :
  80. super_t(x)
  81. {}
  82. template<
  83. typename OtherUnaryFunction,
  84. typename OtherIterator,
  85. typename OtherReference,
  86. typename OtherValue,
  87. typename = enable_if_convertible_t< OtherIterator, Iterator >,
  88. typename = enable_if_convertible_t< OtherUnaryFunction, UnaryFunc >
  89. >
  90. transform_iterator(transform_iterator< OtherUnaryFunction, OtherIterator, OtherReference, OtherValue > const& t) :
  91. super_t(t.base()),
  92. functor_base(boost::empty_init_t{}, t.functor())
  93. {}
  94. UnaryFunc functor() const { return functor_base::get(); }
  95. private:
  96. typename super_t::reference dereference() const { return functor_base::get()(*this->base()); }
  97. };
  98. template< typename UnaryFunc, typename Iterator >
  99. inline transform_iterator< UnaryFunc, Iterator > make_transform_iterator(Iterator it, UnaryFunc fun)
  100. {
  101. return transform_iterator< UnaryFunc, Iterator >(it, fun);
  102. }
  103. // Version which allows explicit specification of the UnaryFunc
  104. // type.
  105. //
  106. // This generator is not provided if UnaryFunc is a function
  107. // pointer type, because it's too dangerous: the default-constructed
  108. // function pointer in the iterator be 0, leading to a runtime
  109. // crash.
  110. template< typename UnaryFunc, typename Iterator >
  111. inline typename std::enable_if<
  112. std::is_class< UnaryFunc >::value, // We should probably find a cheaper test than is_class<>
  113. transform_iterator< UnaryFunc, Iterator >
  114. >::type make_transform_iterator(Iterator it)
  115. {
  116. return transform_iterator< UnaryFunc, Iterator >(it);
  117. }
  118. } // namespace iterators
  119. using iterators::transform_iterator;
  120. using iterators::make_transform_iterator;
  121. } // namespace boost
  122. #endif // BOOST_ITERATOR_TRANSFORM_ITERATOR_23022003THW_HPP