is_iterator.hpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * https://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * Copyright (c) 2023 Andrey Semashev
  7. */
  8. /*!
  9. * \file iterator/is_iterator.hpp
  10. *
  11. * This header contains definition of the \c is_iterator type trait.
  12. */
  13. #ifndef BOOST_ITERATOR_IS_ITERATOR_HPP_INCLUDED_
  14. #define BOOST_ITERATOR_IS_ITERATOR_HPP_INCLUDED_
  15. #include <cstddef>
  16. #include <boost/config.hpp>
  17. #include <boost/type_traits/integral_constant.hpp>
  18. #include <boost/type_traits/negation.hpp>
  19. #include <boost/type_traits/conjunction.hpp>
  20. #include <boost/type_traits/is_complete.hpp>
  21. #include <boost/type_traits/is_function.hpp>
  22. #if !defined(BOOST_NO_CXX17_ITERATOR_TRAITS)
  23. #include <iterator>
  24. #endif
  25. #ifdef BOOST_HAS_PRAGMA_ONCE
  26. #pragma once
  27. #endif
  28. namespace boost {
  29. namespace iterators {
  30. namespace detail {
  31. // The trait attempts to detect if the T type is an iterator class. Class-type iterators are assumed
  32. // to have the nested type iterator_category. Strictly speaking, this is not required to be the
  33. // case (e.g. a user can specialize iterator_traits for T without defining T::iterator_category).
  34. // Still, this is a good heuristic in practice, and we can't do anything better anyway.
  35. // Since C++17 we can test for iterator_traits<T>::iterator_category presence instead as it is
  36. // required to be only present for iterators.
  37. namespace has_iterator_category_detail {
  38. typedef char yes_type;
  39. struct no_type { char padding[2]; };
  40. template< typename T >
  41. yes_type check(
  42. #if !defined(BOOST_NO_CXX17_ITERATOR_TRAITS)
  43. typename std::iterator_traits< T >::iterator_category*
  44. #else
  45. typename T::iterator_category*
  46. #endif
  47. );
  48. template< typename >
  49. no_type check(...);
  50. } // namespace has_iterator_category_detail
  51. template< typename T >
  52. struct is_iterator_impl :
  53. public boost::integral_constant<
  54. bool,
  55. sizeof(has_iterator_category_detail::check< T >(0)) == sizeof(has_iterator_category_detail::yes_type)
  56. >
  57. {
  58. };
  59. template< typename T >
  60. struct is_iterator_impl< T* > :
  61. public boost::conjunction<
  62. boost::is_complete< T >,
  63. boost::negation< boost::is_function< T > >
  64. >::type
  65. {
  66. };
  67. template< typename T, typename U >
  68. struct is_iterator_impl< T U::* > :
  69. public boost::false_type
  70. {
  71. };
  72. template< typename T >
  73. struct is_iterator_impl< T& > :
  74. public boost::false_type
  75. {
  76. };
  77. template< typename T, std::size_t N >
  78. struct is_iterator_impl< T[N] > :
  79. public boost::false_type
  80. {
  81. };
  82. #if !defined(BOOST_TT_HAS_WORKING_IS_COMPLETE)
  83. template< typename T >
  84. struct is_iterator_impl< T[] > :
  85. public boost::false_type
  86. {
  87. };
  88. template< >
  89. struct is_iterator_impl< void > :
  90. public boost::false_type
  91. {
  92. };
  93. template< >
  94. struct is_iterator_impl< void* > :
  95. public boost::false_type
  96. {
  97. };
  98. #endif // !defined(BOOST_TT_HAS_WORKING_IS_COMPLETE)
  99. } // namespace detail
  100. /*!
  101. * \brief The type trait detects whether the type \c T is an iterator type.
  102. *
  103. * The type trait yields \c true if its argument type \c T, after stripping top level
  104. * cv qualifiers, is one of the following:
  105. *
  106. * - A pointer type, other than a pointer to function, a pointer to a class member,
  107. * or a pointer to an incomplete type, including `void`.
  108. * - A class type for which an iterator category is obtainable. Prior to C++17,
  109. * the iterator category must be defined as a public `T::iterator_category` type.
  110. * Since C++17, the expression `std::iterator_traits< T >::iterator_category` must
  111. * be valid and produce the iterator category type.
  112. *
  113. * Otherwise, the type trait yields \c false.
  114. */
  115. template< typename T >
  116. struct is_iterator : public detail::is_iterator_impl< T >::type {};
  117. template< typename T >
  118. struct is_iterator< const T > : public detail::is_iterator_impl< T >::type {};
  119. template< typename T >
  120. struct is_iterator< volatile T > : public detail::is_iterator_impl< T >::type {};
  121. template< typename T >
  122. struct is_iterator< const volatile T > : public detail::is_iterator_impl< T >::type {};
  123. } // namespace iterators
  124. using iterators::is_iterator;
  125. } // namespace boost
  126. #endif // BOOST_ITERATOR_IS_ITERATOR_HPP_INCLUDED_