From cb81a1dfc31d13e21ef1e36e4c96f47139a1b93b Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Tue, 4 Feb 2025 00:53:37 +0300 Subject: [PATCH] Extracted enable_if_convertible trait to a separate header. Keep including the new header in iterator_adaptor.hpp for backward compatibility, until downstream users are updated to include the new header. --- .../boost/iterator/enable_if_convertible.hpp | 84 +++++++++++++++++++ include/boost/iterator/filter_iterator.hpp | 1 + include/boost/iterator/indirect_iterator.hpp | 3 +- include/boost/iterator/iterator_adaptor.hpp | 61 +------------- .../boost/iterator/permutation_iterator.hpp | 2 +- include/boost/iterator/reverse_iterator.hpp | 1 + include/boost/iterator/transform_iterator.hpp | 2 + include/boost/iterator/zip_iterator.hpp | 2 +- test/iterator_adaptor_test.cpp | 1 + 9 files changed, 94 insertions(+), 63 deletions(-) create mode 100644 include/boost/iterator/enable_if_convertible.hpp diff --git a/include/boost/iterator/enable_if_convertible.hpp b/include/boost/iterator/enable_if_convertible.hpp new file mode 100644 index 0000000..d7ff366 --- /dev/null +++ b/include/boost/iterator/enable_if_convertible.hpp @@ -0,0 +1,84 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * https://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2025 Andrey Semashev + */ + +#ifndef BOOST_ITERATOR_ENABLE_IF_CONVERTIBLE_HPP_INCLUDED_ +#define BOOST_ITERATOR_ENABLE_IF_CONVERTIBLE_HPP_INCLUDED_ + +#include + +namespace boost { +namespace iterators { +namespace detail { + +// +// Result type used in enable_if_convertible meta function. +// This can be an incomplete type, as only pointers to +// enable_if_convertible< ... >::type are used. +// We could have used void for this, but conversion to +// void* is just too easy. +// +struct enable_type; + +} // namespace detail + +// +// enable_if for use in adapted iterators constructors. +// +// In order to provide interoperability between adapted constant and +// mutable iterators, adapted iterators will usually provide templated +// conversion constructors of the following form +// +// template +// class adapted_iterator : +// public iterator_adaptor< adapted_iterator, Iterator > +// { +// public: +// +// ... +// +// template +// adapted_iterator( +// OtherIterator const& it +// , typename enable_if_convertible::type* = 0); +// +// ... +// }; +// +// enable_if_convertible is used to remove those overloads from the overload +// set that cannot be instantiated. For all practical purposes only overloads +// for constant/mutable interaction will remain. This has the advantage that +// meta functions like boost::is_convertible do not return false positives, +// as they can only look at the signature of the conversion constructor +// and not at the actual instantiation. +// +// enable_if_interoperable can be safely used in user code. It falls back to +// always enabled for compilers that don't support enable_if or is_convertible. +// There is no need for compiler specific workarounds in user code. +// +// The operators implementation relies on boost::is_convertible not returning +// false positives for user/library defined iterator types. See comments +// on operator implementation for consequences. +// +template< typename From, typename To > +struct enable_if_convertible : + public std::enable_if< + std::is_convertible< From, To >::value, + boost::iterators::detail::enable_type + > +{}; + +template< typename From, typename To > +using enable_if_convertible_t = typename enable_if_convertible< From, To >::type; + +} // namespace iterators + +using iterators::enable_if_convertible; + +} // namespace boost + +#endif // BOOST_ITERATOR_ENABLE_IF_CONVERTIBLE_HPP_INCLUDED_ diff --git a/include/boost/iterator/filter_iterator.hpp b/include/boost/iterator/filter_iterator.hpp index 133fffe..2ec6d79 100644 --- a/include/boost/iterator/filter_iterator.hpp +++ b/include/boost/iterator/filter_iterator.hpp @@ -11,6 +11,7 @@ #include #include +#include #include namespace boost { diff --git a/include/boost/iterator/indirect_iterator.hpp b/include/boost/iterator/indirect_iterator.hpp index ac63aef..ab25e36 100644 --- a/include/boost/iterator/indirect_iterator.hpp +++ b/include/boost/iterator/indirect_iterator.hpp @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -84,7 +85,7 @@ public: typename Category2, typename Reference2, typename Difference2, - typename = typename enable_if_convertible< Iterator2, Iterator >::type + typename = enable_if_convertible_t< Iterator2, Iterator > > indirect_iterator(indirect_iterator< Iterator2, Value2, Category2, Reference2, Difference2 > const& y) : super_t(y.base()) diff --git a/include/boost/iterator/iterator_adaptor.hpp b/include/boost/iterator/iterator_adaptor.hpp index 6abf434..a424236 100644 --- a/include/boost/iterator/iterator_adaptor.hpp +++ b/include/boost/iterator/iterator_adaptor.hpp @@ -14,6 +14,7 @@ #include #include #include +#include // for backward compatibility; remove once downstream users are updated #include @@ -25,65 +26,6 @@ namespace iterators { // explicitly in order to specify that the default should be used. using boost::use_default; -namespace detail { - -// -// Result type used in enable_if_convertible meta function. -// This can be an incomplete type, as only pointers to -// enable_if_convertible< ... >::type are used. -// We could have used void for this, but conversion to -// void* is just too easy. -// -struct enable_type; - -} // namespace detail - -// -// enable_if for use in adapted iterators constructors. -// -// In order to provide interoperability between adapted constant and -// mutable iterators, adapted iterators will usually provide templated -// conversion constructors of the following form -// -// template -// class adapted_iterator : -// public iterator_adaptor< adapted_iterator, Iterator > -// { -// public: -// -// ... -// -// template -// adapted_iterator( -// OtherIterator const& it -// , typename enable_if_convertible::type* = 0); -// -// ... -// }; -// -// enable_if_convertible is used to remove those overloads from the overload -// set that cannot be instantiated. For all practical purposes only overloads -// for constant/mutable interaction will remain. This has the advantage that -// meta functions like boost::is_convertible do not return false positives, -// as they can only look at the signature of the conversion constructor -// and not at the actual instantiation. -// -// enable_if_interoperable can be safely used in user code. It falls back to -// always enabled for compilers that don't support enable_if or is_convertible. -// There is no need for compiler specific workarounds in user code. -// -// The operators implementation relies on boost::is_convertible not returning -// false positives for user/library defined iterator types. See comments -// on operator implementation for consequences. -// -template< typename From, typename To > -struct enable_if_convertible : - public std::enable_if< - std::is_convertible< From, To >::value, - boost::iterators::detail::enable_type - > -{}; - // // Default template argument handling for iterator_adaptor // @@ -297,7 +239,6 @@ private: // data members } // namespace iterators using iterators::iterator_adaptor; -using iterators::enable_if_convertible; } // namespace boost diff --git a/include/boost/iterator/permutation_iterator.hpp b/include/boost/iterator/permutation_iterator.hpp index 186b625..eb15a5a 100644 --- a/include/boost/iterator/permutation_iterator.hpp +++ b/include/boost/iterator/permutation_iterator.hpp @@ -12,7 +12,7 @@ #include #include - +#include namespace boost { namespace iterators { diff --git a/include/boost/iterator/reverse_iterator.hpp b/include/boost/iterator/reverse_iterator.hpp index 03b7925..e2efd85 100644 --- a/include/boost/iterator/reverse_iterator.hpp +++ b/include/boost/iterator/reverse_iterator.hpp @@ -8,6 +8,7 @@ #define BOOST_REVERSE_ITERATOR_23022003THW_HPP #include +#include namespace boost { namespace iterators { diff --git a/include/boost/iterator/transform_iterator.hpp b/include/boost/iterator/transform_iterator.hpp index fd53f36..4ddf929 100644 --- a/include/boost/iterator/transform_iterator.hpp +++ b/include/boost/iterator/transform_iterator.hpp @@ -12,6 +12,8 @@ #include #include #include +#include + #include #include diff --git a/include/boost/iterator/zip_iterator.hpp b/include/boost/iterator/zip_iterator.hpp index 87695a5..ea48b45 100644 --- a/include/boost/iterator/zip_iterator.hpp +++ b/include/boost/iterator/zip_iterator.hpp @@ -10,7 +10,7 @@ #include #include -#include // for enable_if_convertible +#include #include #include diff --git a/test/iterator_adaptor_test.cpp b/test/iterator_adaptor_test.cpp index 9ed8385..d237ac4 100644 --- a/test/iterator_adaptor_test.cpp +++ b/test/iterator_adaptor_test.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include # include