From df9e186bd6a755221b170786d5917ac259fb5192 Mon Sep 17 00:00:00 2001 From: Zach Laine Date: Mon, 5 Jun 2023 00:12:48 -0500 Subject: [PATCH] Add a new v3 namespace, containing a new iterator_interface based on deducing this instead of CRTP. --- doc/intro.qbk | 5 +- doc/tutorial.qbk | 42 +++- example/back_insert_iterator.cpp | 4 + example/filtered_int_iterator.cpp | 2 + example/interoperability.cpp | 2 + example/node_iterator.cpp | 14 +- example/random_access_iterator.cpp | 2 + example/repeated_chars_iterator.cpp | 2 + example/reverse_iterator.cpp | 2 + example/take_view.hpp | 2 + example/zip_proxy_iterator.cpp | 2 + include/boost/stl_interfaces/config.hpp | 31 ++- .../stl_interfaces/iterator_interface.hpp | 192 ++++++++++++++++++ .../boost/stl_interfaces/reverse_iterator.hpp | 27 ++- .../sequence_container_interface.hpp | 15 ++ .../boost/stl_interfaces/view_interface.hpp | 10 + test/bidirectional.cpp | 14 ++ test/compile_sfinae_path_mutable_iterator.cpp | 7 +- test/forward.cpp | 18 +- test/input.cpp | 22 +- test/output.cpp | 18 +- test/random_access.cpp | 14 ++ test/reverse_iter.cpp | 2 + 23 files changed, 416 insertions(+), 33 deletions(-) diff --git a/doc/intro.qbk b/doc/intro.qbk index b9aacb7..ef1fe90 100644 --- a/doc/intro.qbk +++ b/doc/intro.qbk @@ -37,7 +37,10 @@ dramatically. [note C++20 versions of _iter_iface_ and _cont_iface_ are provided (C++20 provides `std::view_interface`). These are constrained templates using C++20 -concepts. These are in the `boost::stl_interfaces::v2` namespace. ] +concepts. These are in the `boost::stl_interfaces::v2` namespace. There is +also a C++23 version of _iter_iface_ that uses deducing `this` instead of +_CRTP_. If you do nothing, you'll get the latest `vN` namespace inlined, +depending on your compiler's language support. ] [heading A Quick Example] diff --git a/doc/tutorial.qbk b/doc/tutorial.qbk index bc91082..4ad1357 100644 --- a/doc/tutorial.qbk +++ b/doc/tutorial.qbk @@ -19,8 +19,9 @@ the full set of operations it supports can be defined in terms of that much smaller basis. It is possible to define any iterator `Iter` in terms of a subset of -user-defined operations. By deriving `Iter` from _iter_iface_ using _CRTP_, -we can generate the full set of operations. Here is the declaration of +user-defined operations. By deriving `Iter` from _iter_iface_, we can +generate the full set of operations. _iter_iface_ uses _CRTP_ in C++20 and +earlier, and deducing `this` in C++23 and later. Here is the declaration of _iter_iface_: template< @@ -32,10 +33,24 @@ _iter_iface_: typename DifferenceType = std::ptrdiff_t> struct iterator_interface; +Or, for C++23 and later: + + template< + typename IteratorConcept, + typename ValueType, + typename Reference = ValueType &, + typename Pointer = ValueType *, + typename DifferenceType = std::ptrdiff_t> + struct iterator_interface; + Let's break that down. `Derived` is the type that you're deriving _iter_iface_ from. +[important In C++23 and later, as long as you have not defined +`BOOST_STL_INTERFACES_DISABLE_DEDUCED_THIS`, you do not pass the derived type +to _iter_iface_; it has no `Derived` template parameter.] + `IteratorConcept` defines the iterator category/concept. This must be one of the C++ standard iterator tag types, like `std::forward_iterator_tag`. In C++20 and later, `std::contiguous_iterator_tag` is a valid tag to use. @@ -85,12 +100,30 @@ reasonable defaults for _iter_iface_'s parameters: proxy_arrow_result, DifferenceType>; +Or, for C++23 and later: + + template< + typename IteratorConcept, + typename ValueType, + typename Reference = ValueType, + typename DifferenceType = std::ptrdiff_t> + using proxy_iterator_interface = iterator_interface< + IteratorConcept, + ValueType, + Reference, + proxy_arrow_result, + DifferenceType>; + [note As shown above, _proxy_iter_iface_ uses a template called `proxy_arrow_result` as its pointer-type. This template makes a copy of whatever value is obtained by `operator*`, and then returns a pointer to the copy in its `operator->`. You may want to use something else if this is a performance concern. ] +[important If you are using C++23 or later and have not defined +`BOOST_STL_INTERFACES_DISABLE_DEDUCED_THIS`, the `Derived` template parameter +above will not be present.] + [heading User-Defined Iterator Operations] @@ -231,8 +264,9 @@ will get us there. [node_iterator_class_head] We are deriving `node_iterator` from _iter_iface_, and because we're using -_CRTP_, we first have to pass `node_iterator` for the `Derived` template -parameter, so that _iter_iface_ knows what derived type to cast to in order to +_CRTP_ in C++20 and earlier, we first have to pass `node_iterator` for the +`Derived` template parameter if `BOOST_STL_INTERFACES_USE_DEDUCED_THIS` is not +defined, so that _iter_iface_ knows what derived type to cast to in order to get at the user-defined operations. Then, we pass `std::forward_iterator_tag` for `IteratorConcept`, since that's appropriate for a singly-linked list. Finally, we pass `T` to let _iter_iface_ know what the `value_type` is for our diff --git a/example/back_insert_iterator.cpp b/example/back_insert_iterator.cpp index 9bef646..6e07ea0 100644 --- a/example/back_insert_iterator.cpp +++ b/example/back_insert_iterator.cpp @@ -19,7 +19,9 @@ // iterator_interface is flexible enough to handle this odd kind of iterator. template struct back_insert_iterator : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS back_insert_iterator, +#endif std::output_iterator_tag, typename Container::value_type, back_insert_iterator &> @@ -51,7 +53,9 @@ struct back_insert_iterator : boost::stl_interfaces::iterator_interface< back_insert_iterator & operator++() { return *this; } using base_type = boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS back_insert_iterator, +#endif std::output_iterator_tag, typename Container::value_type, back_insert_iterator &>; diff --git a/example/filtered_int_iterator.cpp b/example/filtered_int_iterator.cpp index a788cc5..30ce72d 100644 --- a/example/filtered_int_iterator.cpp +++ b/example/filtered_int_iterator.cpp @@ -15,7 +15,9 @@ //[ filtered_int_iterator_defn template struct filtered_int_iterator : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS filtered_int_iterator, +#endif std::bidirectional_iterator_tag, int> { diff --git a/example/interoperability.cpp b/example/interoperability.cpp index 7c69b0e..5725c2b 100644 --- a/example/interoperability.cpp +++ b/example/interoperability.cpp @@ -18,7 +18,9 @@ // from the same template. template struct random_access_iterator : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS random_access_iterator, +#endif std::random_access_iterator_tag, ValueType> { diff --git a/example/node_iterator.cpp b/example/node_iterator.cpp index 752638d..dd05938 100644 --- a/example/node_iterator.cpp +++ b/example/node_iterator.cpp @@ -24,8 +24,11 @@ struct node //[ node_iterator_class_head template struct node_iterator - : boost::stl_interfaces:: - iterator_interface, std::forward_iterator_tag, T> + : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + node_iterator, +#endif + std::forward_iterator_tag, T> //] { //[ node_iterator_ctors @@ -48,8 +51,11 @@ struct node_iterator //] //[ node_iterator_using_declaration - using base_type = boost::stl_interfaces:: - iterator_interface, std::forward_iterator_tag, T>; + using base_type = boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + node_iterator, +#endif + std::forward_iterator_tag, T>; using base_type::operator++; //] diff --git a/example/random_access_iterator.cpp b/example/random_access_iterator.cpp index 1d5071f..470bea7 100644 --- a/example/random_access_iterator.cpp +++ b/example/random_access_iterator.cpp @@ -16,7 +16,9 @@ // parameters for most stl_interfaces template parameters. struct simple_random_access_iterator : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS simple_random_access_iterator, +#endif std::random_access_iterator_tag, int> { diff --git a/example/repeated_chars_iterator.cpp b/example/repeated_chars_iterator.cpp index 83a158b..c3737cf 100644 --- a/example/repeated_chars_iterator.cpp +++ b/example/repeated_chars_iterator.cpp @@ -12,7 +12,9 @@ //[ repeated_chars_iterator struct repeated_chars_iterator : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS repeated_chars_iterator, +#endif std::random_access_iterator_tag, char, char> diff --git a/example/reverse_iterator.cpp b/example/reverse_iterator.cpp index 217fca7..37ef994 100644 --- a/example/reverse_iterator.cpp +++ b/example/reverse_iterator.cpp @@ -21,7 +21,9 @@ template struct reverse_iterator : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS reverse_iterator, +#endif #if 201703L < __cplusplus && defined(__cpp_lib_ranges) boost::stl_interfaces::v2::v2_dtl::iter_concept_t, #else diff --git a/example/take_view.hpp b/example/take_view.hpp index af00ef5..ac072ea 100644 --- a/example/take_view.hpp +++ b/example/take_view.hpp @@ -15,7 +15,9 @@ namespace detail { template struct take_iterator : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS take_iterator, +#endif std::forward_iterator_tag, typename std::iterator_traits::value_type, typename std::iterator_traits::reference, diff --git a/example/zip_proxy_iterator.cpp b/example/zip_proxy_iterator.cpp index 4a73e07..6029b87 100644 --- a/example/zip_proxy_iterator.cpp +++ b/example/zip_proxy_iterator.cpp @@ -19,7 +19,9 @@ // reference -- the reference type is a pair of references, std::tuple. struct zip_iterator : boost::stl_interfaces::proxy_iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS zip_iterator, +#endif std::random_access_iterator_tag, std::tuple, std::tuple> diff --git a/include/boost/stl_interfaces/config.hpp b/include/boost/stl_interfaces/config.hpp index b4eec66..f014bba 100644 --- a/include/boost/stl_interfaces/config.hpp +++ b/include/boost/stl_interfaces/config.hpp @@ -17,17 +17,32 @@ #define BOOST_STL_INTERFACES_USE_CONCEPTS 0 #endif -// The inline namespaces v1 and v2 represent pre- and post-C++20. v1 is -// inline for standards before C++20, and v2 is inline for C++20 and later. -// Note that this only applies to code for which a v2 namespace alternative -// exists. Some instances of the v1 namespace may still be inline, if there -// is no v2 version of its contents. -#if BOOST_STL_INTERFACES_USE_CONCEPTS -# define BOOST_STL_INTERFACES_NAMESPACE_V1 namespace v1 -# define BOOST_STL_INTERFACES_NAMESPACE_V2 inline namespace v2 +#if defined(__cpp_explicit_this_parameter) && \ + BOOST_STL_INTERFACES_USE_CONCEPTS && \ + !defined(BOOST_STL_INTERFACES_DISABLE_DEDUCED_THIS) +#define BOOST_STL_INTERFACES_USE_DEDUCED_THIS 1 #else +#define BOOST_STL_INTERFACES_USE_DEDUCED_THIS 0 +#endif + +// The inline namespaces v1, v2, and v3 represent C++14, C++20, and C++23 and +// later, respectively. v1 is inline for standards before C++20, and v2 is +// inline for C++20 and later. Note that this only applies to code for which +// multiple vI namespace alternatives exist. For example, some instances of +// the v1 namespace may still be inline, if there is no v2 version of its +// contents. +#if !BOOST_STL_INTERFACES_USE_CONCEPTS && !BOOST_STL_INTERFACES_USE_DEDUCED_THIS # define BOOST_STL_INTERFACES_NAMESPACE_V1 inline namespace v1 # define BOOST_STL_INTERFACES_NAMESPACE_V2 namespace v2 +# define BOOST_STL_INTERFACES_NAMESPACE_V3 namespace v3 +#elif BOOST_STL_INTERFACES_USE_CONCEPTS && !BOOST_STL_INTERFACES_USE_DEDUCED_THIS +# define BOOST_STL_INTERFACES_NAMESPACE_V1 namespace v1 +# define BOOST_STL_INTERFACES_NAMESPACE_V2 inline namespace v2 +# define BOOST_STL_INTERFACES_NAMESPACE_V3 namespace v3 +#else +# define BOOST_STL_INTERFACES_NAMESPACE_V1 namespace v1 +# define BOOST_STL_INTERFACES_NAMESPACE_V2 namespace v2 +# define BOOST_STL_INTERFACES_NAMESPACE_V3 inline namespace v3 #endif #endif diff --git a/include/boost/stl_interfaces/iterator_interface.hpp b/include/boost/stl_interfaces/iterator_interface.hpp index 5c29f55..ec1e474 100644 --- a/include/boost/stl_interfaces/iterator_interface.hpp +++ b/include/boost/stl_interfaces/iterator_interface.hpp @@ -922,6 +922,198 @@ namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V2 { #endif +#if defined(BOOST_STL_INTERFACES_DOXYGEN) || BOOST_STL_INTERFACES_USE_DEDUCED_THIS + +namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V3 { + + // clang-format off + + /** A base template that one may derive from to make defining iterators + easier. */ + template< + typename IteratorConcept, + typename ValueType, + typename Reference = ValueType &, + typename Pointer = ValueType *, + typename DifferenceType = std::ptrdiff_t> + struct iterator_interface + : v2::v2_dtl::iterator_category_base + { + using iterator_concept = IteratorConcept; + using value_type = std::remove_const_t; + using reference = Reference; + using pointer = detail::pointer_t; + using difference_type = DifferenceType; + + constexpr decltype(auto) operator*(this auto&& self) + requires requires { *access::base(self); } { + return *access::base(self); + } + + constexpr auto operator->(this auto&& self) + requires (!std::same_as) && std::is_reference_v && requires { *self; } { + return detail::make_pointer(*self); + } + + constexpr decltype(auto) operator[](this auto const& self, difference_type n) + requires requires { self + n; } { + auto retval = self; + retval = retval + n; + return *retval; + } + + constexpr decltype(auto) operator++(this auto& self) + requires requires { ++access::base(self); } && (!requires { self += difference_type(1); }) { + ++access::base(self); + return self; + } + constexpr decltype(auto) operator++(this auto& self) + requires requires { self += difference_type(1); } { + return self += difference_type(1); + } + constexpr auto operator++(this auto& self, int) requires requires { ++self; } { + if constexpr (std::is_same_v){ + ++self; + } else { + auto retval = self; + ++self; + return retval; + } + } + constexpr decltype(auto) operator+=(this auto& self, difference_type n) + requires requires { access::base(self) += n; } { + access::base(self) += n; + return self; + } + + constexpr decltype(auto) operator--(this auto& self) + requires requires { --access::base(self); } && (!requires { self += difference_type(1); }) { + --access::base(self); + return self; + } + constexpr decltype(auto) operator--(this auto& self) + requires requires { self += -difference_type(1); } { + return self += -difference_type(1); + } + constexpr auto operator--(this auto& self, int) requires requires { --self; } { + auto retval = self; + --self; + return retval; + } + constexpr decltype(auto) operator-=(this auto& self, difference_type n) + requires requires { self += -n; } { + return self += -n; + } + }; + + namespace v3_dtl { + template< + typename IteratorConcept, + typename ValueType, + typename Reference, + typename Pointer, + typename DifferenceType> + void derived_iterator(v3::iterator_interface< + IteratorConcept, + ValueType, + Reference, + Pointer, + DifferenceType> const &); + + template + concept derived_iter = requires (D d) { v3_dtl::derived_iterator(d); }; + } + + template + constexpr auto operator+(D it, typename D::difference_type n) + requires v3_dtl::derived_iter && requires { it += n; } + { return it += n; } + template + constexpr auto operator+(typename D::difference_type n, D it) + requires v3_dtl::derived_iter && requires { it += n; } + { return it += n; } + + template + constexpr auto operator-(D1 lhs, D2 rhs) + requires v3_dtl::derived_iter && v3_dtl::derived_iter && + requires { access::base(lhs) - access::base(rhs); } + { return access::base(lhs) - access::base(rhs); } + template + constexpr auto operator-(D it, typename D::difference_type n) + requires v3_dtl::derived_iter && requires { it += -n; } + { return it += -n; } + +#if defined(__cpp_lib_three_way_comparison) + template + constexpr auto operator<=>(D1 lhs, D2 rhs) + requires v3_dtl::derived_iter && v3_dtl::derived_iter && + (v2::v2_dtl::base_3way || v2::v2_dtl::iter_sub) { + if constexpr (v2::v2_dtl::base_3way) { + return access::base(lhs) <=> access::base(rhs); + } else { + using diff_type = typename D1::difference_type; + diff_type const diff = rhs - lhs; + return diff < diff_type(0) ? std::strong_ordering::less : + diff_type(0) < diff ? std::strong_ordering::greater : + std::strong_ordering::equal; + } + } +#endif + template + constexpr bool operator<(D1 lhs, D2 rhs) + requires v3_dtl::derived_iter && v3_dtl::derived_iter && v2::v2_dtl::iter_sub + { return (lhs - rhs) < typename D1::difference_type(0); } + template + constexpr bool operator<=(D1 lhs, D2 rhs) + requires v3_dtl::derived_iter && v3_dtl::derived_iter && v2::v2_dtl::iter_sub + { return (lhs - rhs) <= typename D1::difference_type(0); } + template + constexpr bool operator>(D1 lhs, D2 rhs) + requires v3_dtl::derived_iter && v3_dtl::derived_iter && v2::v2_dtl::iter_sub + { return (lhs - rhs) > typename D1::difference_type(0); } + template + constexpr bool operator>=(D1 lhs, D2 rhs) + requires v3_dtl::derived_iter && v3_dtl::derived_iter && v2::v2_dtl::iter_sub + { return (lhs - rhs) >= typename D1::difference_type(0); } + + template + constexpr bool operator==(D1 lhs, D2 rhs) + requires v3_dtl::derived_iter && v3_dtl::derived_iter && + detail::interoperable::value && + (v2::v2_dtl::base_eq || v2::v2_dtl::iter_sub) { + if constexpr (v2::v2_dtl::base_eq) { + return (access::base(lhs) == access::base(rhs)); + } else if constexpr (v2::v2_dtl::iter_sub) { + return (lhs - rhs) == typename D1::difference_type(0); + } + } + + template + constexpr auto operator!=(D1 lhs, D2 rhs) -> decltype(!(lhs == rhs)) + requires v3_dtl::derived_iter && v3_dtl::derived_iter + { return !(lhs == rhs); } + + // clang-format on + + + /** A template alias useful for defining proxy iterators. \see + `iterator_interface`. */ + template< + typename IteratorConcept, + typename ValueType, + typename Reference = ValueType, + typename DifferenceType = std::ptrdiff_t> + using proxy_iterator_interface = iterator_interface< + IteratorConcept, + ValueType, + Reference, + proxy_arrow_result, + DifferenceType>; + +}}} + +#endif + #ifdef BOOST_STL_INTERFACES_DOXYGEN /** `static_asserts` that type `type` models concept `concept_name`. This is diff --git a/include/boost/stl_interfaces/reverse_iterator.hpp b/include/boost/stl_interfaces/reverse_iterator.hpp index 6827649..8692b82 100644 --- a/include/boost/stl_interfaces/reverse_iterator.hpp +++ b/include/boost/stl_interfaces/reverse_iterator.hpp @@ -62,7 +62,9 @@ namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V1 { template struct reverse_iterator : iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS reverse_iterator, +#endif #if BOOST_STL_INTERFACES_USE_CONCEPTS typename boost::stl_interfaces::v2::v2_dtl::iter_concept_t< BidiIter>, @@ -160,7 +162,7 @@ namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V1 { } /** Makes a `reverse_iterator` from an iterator of type - `Bidiiter`. */ + `BidiIter`. */ template auto make_reverse_iterator(BidiIter it) { @@ -182,7 +184,28 @@ namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V2 { /** Makes a `reverse_iterator` from an iterator of type - `Bidiiter`. This only exists to make migration from + `BidiIter`. This only exists to make migration from + Boost.STLInterfaces to C++20 easier; switch to the one in `std` as + soon as you can. */ + template + auto make_reverse_iterator(BidiIter it) + { + return reverse_iterator(it); + } + +}}} + +namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V3 { + + /** A template alias for `std::reverse_iterator`. This only exists to + make migration from Boost.STLInterfaces to C++20 easier; switch to the + one in `std` as soon as you can. */ + template + using reverse_iterator = std::reverse_iterator; + + + /** Makes a `reverse_iterator` from an iterator of type + `BidiIter`. This only exists to make migration from Boost.STLInterfaces to C++20 easier; switch to the one in `std` as soon as you can. */ template diff --git a/include/boost/stl_interfaces/sequence_container_interface.hpp b/include/boost/stl_interfaces/sequence_container_interface.hpp index 1f3732b..233f551 100644 --- a/include/boost/stl_interfaces/sequence_container_interface.hpp +++ b/include/boost/stl_interfaces/sequence_container_interface.hpp @@ -20,7 +20,9 @@ namespace boost { namespace stl_interfaces { namespace detail { template struct n_iter : iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS n_iter, +#endif std::random_access_iterator_tag, T> { @@ -1025,4 +1027,17 @@ namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V2 { #endif +#if defined(BOOST_STL_INTERFACES_DOXYGEN) || BOOST_STL_INTERFACES_USE_DEDUCED_THIS + +namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V3 { + + // TODO: Reimplement using deduced this. + template + using sequence_container_interface = v2::sequence_container_interface; + +}}} + +#endif + #endif diff --git a/include/boost/stl_interfaces/view_interface.hpp b/include/boost/stl_interfaces/view_interface.hpp index 0ed657c..88e6821 100644 --- a/include/boost/stl_interfaces/view_interface.hpp +++ b/include/boost/stl_interfaces/view_interface.hpp @@ -213,6 +213,16 @@ namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V2 { }}} +namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V3 { + + /** A template alias for `std::ranges::view_interface`. This only exists + to make migration from Boost.STLInterfaces to C++20 easier; switch to + the one in `std` as soon as you can. */ + template + using view_interface = std::ranges::view_interface; + +}}} + #endif #endif diff --git a/test/bidirectional.cpp b/test/bidirectional.cpp index 1b51578..e9cbd6a 100644 --- a/test/bidirectional.cpp +++ b/test/bidirectional.cpp @@ -18,7 +18,9 @@ struct basic_bidirectional_iter : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS basic_bidirectional_iter, +#endif std::bidirectional_iterator_tag, int> { @@ -43,7 +45,9 @@ struct basic_bidirectional_iter : boost::stl_interfaces::iterator_interface< } using base_type = boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS basic_bidirectional_iter, +#endif std::bidirectional_iterator_tag, int>; using base_type::operator++; @@ -71,7 +75,9 @@ static_assert( struct basic_adapted_bidirectional_ptr_iter : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS basic_adapted_bidirectional_ptr_iter, +#endif std::bidirectional_iterator_tag, int> { @@ -99,7 +105,9 @@ BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( struct basic_adapted_bidirectional_list_iter : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS basic_adapted_bidirectional_list_iter, +#endif std::bidirectional_iterator_tag, int> { @@ -129,7 +137,9 @@ BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( template struct adapted_bidirectional_ptr_iter : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS adapted_bidirectional_ptr_iter, +#endif std::bidirectional_iterator_tag, ValueType> { @@ -185,7 +195,9 @@ BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( template struct bidirectional_iter : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS bidirectional_iter, +#endif std::bidirectional_iterator_tag, ValueType> { @@ -216,7 +228,9 @@ struct bidirectional_iter : boost::stl_interfaces::iterator_interface< } using base_type = boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS bidirectional_iter, +#endif std::bidirectional_iterator_tag, ValueType>; using base_type::operator++; diff --git a/test/compile_sfinae_path_mutable_iterator.cpp b/test/compile_sfinae_path_mutable_iterator.cpp index c499370..6018b3d 100644 --- a/test/compile_sfinae_path_mutable_iterator.cpp +++ b/test/compile_sfinae_path_mutable_iterator.cpp @@ -17,8 +17,11 @@ struct node template struct iterator - : boost::stl_interfaces:: - iterator_interface, std::forward_iterator_tag, Node> + : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + iterator, +#endif + std::forward_iterator_tag, Node> { using value_type = typename Node::value_type; diff --git a/test/forward.cpp b/test/forward.cpp index 51e9ed9..aba54ee 100644 --- a/test/forward.cpp +++ b/test/forward.cpp @@ -19,8 +19,11 @@ template using decrementable_t = decltype(--std::declval()); struct basic_forward_iter - : boost::stl_interfaces:: - iterator_interface + : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + basic_forward_iter, +#endif + std::forward_iterator_tag, int> { basic_forward_iter() : it_(nullptr) {} basic_forward_iter(int * it) : it_(it) {} @@ -37,8 +40,11 @@ struct basic_forward_iter return lhs.it_ == rhs.it_; } - using base_type = boost::stl_interfaces:: - iterator_interface; + using base_type = boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + basic_forward_iter, +#endif + std::forward_iterator_tag, int>; using base_type::operator++; private: @@ -60,7 +66,9 @@ static_assert(ill_formed::value, ""); template struct forward_iter : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS forward_iter, +#endif std::forward_iterator_tag, ValueType> { @@ -85,7 +93,9 @@ struct forward_iter : boost::stl_interfaces::iterator_interface< } using base_type = boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS forward_iter, +#endif std::forward_iterator_tag, ValueType>; using base_type::operator++; diff --git a/test/input.cpp b/test/input.cpp index 0fb0763..41894cd 100644 --- a/test/input.cpp +++ b/test/input.cpp @@ -16,8 +16,11 @@ struct basic_input_iter - : boost::stl_interfaces:: - iterator_interface + : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + basic_input_iter, +#endif + std::input_iterator_tag, int> { basic_input_iter() : it_(nullptr) {} basic_input_iter(int * it) : it_(it) {} @@ -33,8 +36,11 @@ struct basic_input_iter return lhs.it_ == rhs.it_; } - using base_type = boost::stl_interfaces:: - iterator_interface; + using base_type = boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + basic_input_iter, +#endif + std::input_iterator_tag, int>; using base_type::operator++; private: @@ -56,7 +62,9 @@ BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( template struct input_iter : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS input_iter, +#endif std::input_iterator_tag, ValueType> { @@ -81,7 +89,9 @@ struct input_iter : boost::stl_interfaces::iterator_interface< } using base_type = boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS input_iter, +#endif std::input_iterator_tag, ValueType>; using base_type::operator++; @@ -112,7 +122,9 @@ using const_pair_input = input_iter const>; template struct proxy_input_iter : boost::stl_interfaces::proxy_iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS proxy_input_iter, +#endif std::input_iterator_tag, ValueType> { @@ -137,7 +149,9 @@ struct proxy_input_iter : boost::stl_interfaces::proxy_iterator_interface< } using base_type = boost::stl_interfaces::proxy_iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS proxy_input_iter, +#endif std::input_iterator_tag, ValueType>; using base_type::operator++; diff --git a/test/output.cpp b/test/output.cpp index 88cc320..5075332 100644 --- a/test/output.cpp +++ b/test/output.cpp @@ -14,8 +14,11 @@ struct basic_output_iter - : boost::stl_interfaces:: - iterator_interface + : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + basic_output_iter, +#endif + std::output_iterator_tag, int> { basic_output_iter() : it_(nullptr) {} basic_output_iter(int * it) : it_(it) {} @@ -27,8 +30,11 @@ struct basic_output_iter return *this; } - using base_type = boost::stl_interfaces:: - iterator_interface; + using base_type = boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + basic_output_iter, +#endif + std::output_iterator_tag, int>; using base_type::operator++; private: @@ -61,7 +67,9 @@ BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( template struct back_insert_iter : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS back_insert_iter, +#endif std::output_iterator_tag, typename Container::value_type, back_insert_iter &> @@ -84,7 +92,9 @@ struct back_insert_iter : boost::stl_interfaces::iterator_interface< } using base_type = boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS back_insert_iter, +#endif std::output_iterator_tag, typename Container::value_type, back_insert_iter &>; diff --git a/test/random_access.cpp b/test/random_access.cpp index a43dbc6..3d3a90f 100644 --- a/test/random_access.cpp +++ b/test/random_access.cpp @@ -18,7 +18,9 @@ struct basic_random_access_iter : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS basic_random_access_iter, +#endif std::random_access_iterator_tag, int> { @@ -63,7 +65,9 @@ static_assert( template struct basic_random_access_iter_dependent : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS basic_random_access_iter_dependent, +#endif std::random_access_iterator_tag, ValueType> { @@ -103,7 +107,9 @@ BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( struct basic_adapted_random_access_iter : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS basic_adapted_random_access_iter, +#endif std::random_access_iterator_tag, int> { @@ -131,7 +137,9 @@ BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( template struct adapted_random_access_iter : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS adapted_random_access_iter, +#endif std::random_access_iterator_tag, ValueType> { @@ -180,7 +188,9 @@ BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( template struct random_access_iter : boost::stl_interfaces::iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS random_access_iter, +#endif std::random_access_iterator_tag, ValueType> { @@ -238,7 +248,9 @@ BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( std::ptrdiff_t) struct zip_iter : boost::stl_interfaces::proxy_iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS zip_iter, +#endif std::random_access_iterator_tag, std::tuple, std::tuple> @@ -298,7 +310,9 @@ struct int_t }; struct udt_zip_iter : boost::stl_interfaces::proxy_iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS udt_zip_iter, +#endif std::random_access_iterator_tag, std::tuple, std::tuple> diff --git a/test/reverse_iter.cpp b/test/reverse_iter.cpp index 661426c..76db6fb 100644 --- a/test/reverse_iter.cpp +++ b/test/reverse_iter.cpp @@ -16,7 +16,9 @@ struct zip_iter : boost::stl_interfaces::proxy_iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS zip_iter, +#endif std::random_access_iterator_tag, std::tuple, std::tuple>