enable_if_convertible.hpp 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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) 2025 Andrey Semashev
  7. */
  8. #ifndef BOOST_ITERATOR_ENABLE_IF_CONVERTIBLE_HPP_INCLUDED_
  9. #define BOOST_ITERATOR_ENABLE_IF_CONVERTIBLE_HPP_INCLUDED_
  10. #include <type_traits>
  11. namespace boost {
  12. namespace iterators {
  13. namespace detail {
  14. //
  15. // Result type used in enable_if_convertible meta function.
  16. // This can be an incomplete type, as only pointers to
  17. // enable_if_convertible< ... >::type are used.
  18. // We could have used void for this, but conversion to
  19. // void* is just too easy.
  20. //
  21. struct enable_type;
  22. } // namespace detail
  23. //
  24. // enable_if for use in adapted iterators constructors.
  25. //
  26. // In order to provide interoperability between adapted constant and
  27. // mutable iterators, adapted iterators will usually provide templated
  28. // conversion constructors of the following form
  29. //
  30. // template <class BaseIterator>
  31. // class adapted_iterator :
  32. // public iterator_adaptor< adapted_iterator<Iterator>, Iterator >
  33. // {
  34. // public:
  35. //
  36. // ...
  37. //
  38. // template <class OtherIterator>
  39. // adapted_iterator(
  40. // OtherIterator const& it
  41. // , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0);
  42. //
  43. // ...
  44. // };
  45. //
  46. // enable_if_convertible is used to remove those overloads from the overload
  47. // set that cannot be instantiated. For all practical purposes only overloads
  48. // for constant/mutable interaction will remain. This has the advantage that
  49. // meta functions like boost::is_convertible do not return false positives,
  50. // as they can only look at the signature of the conversion constructor
  51. // and not at the actual instantiation.
  52. //
  53. // enable_if_interoperable can be safely used in user code. It falls back to
  54. // always enabled for compilers that don't support enable_if or is_convertible.
  55. // There is no need for compiler specific workarounds in user code.
  56. //
  57. // The operators implementation relies on boost::is_convertible not returning
  58. // false positives for user/library defined iterator types. See comments
  59. // on operator implementation for consequences.
  60. //
  61. template< typename From, typename To >
  62. struct enable_if_convertible :
  63. public std::enable_if<
  64. std::is_convertible< From, To >::value,
  65. boost::iterators::detail::enable_type
  66. >
  67. {};
  68. template< typename From, typename To >
  69. using enable_if_convertible_t = typename enable_if_convertible< From, To >::type;
  70. } // namespace iterators
  71. using iterators::enable_if_convertible;
  72. } // namespace boost
  73. #endif // BOOST_ITERATOR_ENABLE_IF_CONVERTIBLE_HPP_INCLUDED_