is_iterator.hpp 4.0 KB

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