Skip to content

Commit b5f416b

Browse files
committed
Introduce ext_iterator_interface_compat.
This is more ergonomic than having two different versions of interator_interface without having different names.
1 parent 7e62b40 commit b5f416b

File tree

2 files changed

+51
-31
lines changed

2 files changed

+51
-31
lines changed

include/beman/iterator_interface26/iterator_interface.hpp

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ class proxy_arrow_result {
4545
constexpr T* operator->() noexcept { return &value_; }
4646
};
4747

48-
4948
// [iterator.interface.tmpl], class template iterator_interface
5049
template <class IteratorConcept,
5150
class ValueType,
@@ -141,7 +140,7 @@ struct iter_cat<IteratorConcept, ReferenceType, false> {};
141140

142141
template <typename IteratorConcept, typename ReferenceType>
143142
struct iter_cat<IteratorConcept, ReferenceType, true> {
144-
constexpr static auto compute_category_tag() {
143+
static constexpr auto compute_category_tag() {
145144
if constexpr (!std::is_reference_v<ReferenceType>) {
146145
return std::input_iterator_tag{};
147146
} else if constexpr (std::is_base_of_v<std::random_access_iterator_tag, IteratorConcept>) {
@@ -153,7 +152,7 @@ struct iter_cat<IteratorConcept, ReferenceType, true> {
153152
}
154153
}
155154

156-
using TagType = std::invoke_result_t<decltype(compute_category_tag)>;
155+
using TagType = std::invoke_result_t<decltype(compute_category_tag)>;
157156
using iterator_category = TagType;
158157
};
159158

@@ -162,13 +161,14 @@ struct iter_cat<IteratorConcept, ReferenceType, true> {
162161
template <class IteratorConcept, class ValueType, class Reference, class Pointer, class DifferenceType>
163162
class iterator_interface {
164163
public:
165-
using iterator_concept = IteratorConcept;
166-
using iterator_category = detail::iter_cat < IteratorConcept, Reference,
167-
std::derived_from<IteratorConcept, std::forward_iterator_tag>>::iterator_category;
168-
using value_type = remove_const_t<ValueType>;
169-
using reference = Reference;
170-
using pointer = conditional_t<is_same_v<iterator_concept, output_iterator_tag>, void, Pointer>;
171-
using difference_type = DifferenceType;
164+
using iterator_concept = IteratorConcept;
165+
using iterator_category =
166+
detail::iter_cat<IteratorConcept, Reference, std::derived_from<IteratorConcept, std::forward_iterator_tag>>::
167+
iterator_category;
168+
using value_type = remove_const_t<ValueType>;
169+
using reference = Reference;
170+
using pointer = conditional_t<is_same_v<iterator_concept, output_iterator_tag>, void, Pointer>;
171+
using difference_type = DifferenceType;
172172

173173
constexpr decltype(auto) operator*(this auto&& self)
174174
requires requires { *iterator_interface_access::base(self); }
@@ -332,9 +332,43 @@ constexpr bool operator==(D1 lhs, D2 rhs)
332332
}
333333
}
334334

335+
template <typename Derived,
336+
typename IteratorConcept,
337+
typename ValueType,
338+
typename Reference = ValueType&,
339+
typename Pointer = ValueType*,
340+
typename DifferenceType = std::ptrdiff_t>
341+
using ext_iterator_interface_compat =
342+
iterator_interface<IteratorConcept, ValueType, Reference, Pointer, DifferenceType>;
343+
335344
#else
336345

337-
using detail::stl_interfaces::iterator_interface;
346+
namespace detail {
347+
template <class>
348+
constexpr bool dependent_false = false; // workaround before CWG2518/P2593R1
349+
}
350+
351+
template <class IteratorConcept,
352+
class ValueType,
353+
class Reference = ValueType&,
354+
class Pointer = ValueType*,
355+
class DifferenceType = std::ptrdiff_t>
356+
class iterator_interface {
357+
static_assert(detail::dependent_false<IteratorConcept>,
358+
"beman.iterator_interface was compiled with "
359+
"BEMAN_ITERATOR_INTERFACE26_USE_DEDUCING_THIS set to FALSE so "
360+
"beman::iterator_interface26::iterator_interface is not available. See "
361+
"beman::iterator_interface26::ext_iterator_interface_compat for a portable alternative.");
362+
};
363+
364+
template <typename Derived,
365+
typename IteratorConcept,
366+
typename ValueType,
367+
typename Reference = ValueType&,
368+
typename Pointer = ValueType*,
369+
typename DifferenceType = std::ptrdiff_t>
370+
using ext_iterator_interface_compat = detail::stl_interfaces::
371+
iterator_interface<Derived, IteratorConcept, ValueType, Reference, Pointer, DifferenceType>;
338372

339373
#endif
340374

src/beman/iterator_interface26/iterator_interface.t.cpp

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,8 @@ namespace {} // namespace
1414

1515
TEST(IteratorTest, TestGTest) { ASSERT_EQ(1, 1); }
1616

17-
struct repeated_chars_iterator : iterator_interface<
18-
#if !BEMAN_ITERATOR_INTERFACE26_USE_DEDUCING_THIS()
19-
repeated_chars_iterator,
20-
#endif
21-
std::random_access_iterator_tag,
22-
char,
23-
char> {
17+
struct repeated_chars_iterator
18+
: ext_iterator_interface_compat<repeated_chars_iterator, std::random_access_iterator_tag, char, char> {
2419
constexpr repeated_chars_iterator() : first_(nullptr), size_(0), n_(0) {}
2520
constexpr repeated_chars_iterator(const char* first, difference_type size, difference_type n)
2621
: first_(first), size_(size), n_(n) {}
@@ -47,12 +42,8 @@ TEST(IteratorTest, TestRepeatedChars) {
4742
}
4843

4944
template <typename Pred>
50-
struct filtered_int_iterator : iterator_interface<
51-
#if !BEMAN_ITERATOR_INTERFACE26_USE_DEDUCING_THIS()
52-
filtered_int_iterator<Pred>,
53-
#endif
54-
std::forward_iterator_tag,
55-
int> {
45+
struct filtered_int_iterator
46+
: ext_iterator_interface_compat<filtered_int_iterator<Pred>, std::forward_iterator_tag, int> {
5647
filtered_int_iterator() : it_(nullptr) {}
5748
filtered_int_iterator(int* it, int* last, Pred pred) : it_(it), last_(last), pred_(std::move(pred)) {
5849
it_ = std::find_if(it_, last_, pred_);
@@ -101,13 +92,8 @@ struct ClassWithMemberFunction {
10192
int f() { return 3; }
10293
};
10394

104-
struct AlwaysIterator : iterator_interface<
105-
#if !BEMAN_ITERATOR_INTERFACE26_USE_DEDUCING_THIS()
106-
AlwaysIterator,
107-
#endif
108-
109-
std::random_access_iterator_tag,
110-
ClassWithMemberFunction> {
95+
struct AlwaysIterator
96+
: ext_iterator_interface_compat<AlwaysIterator, std::random_access_iterator_tag, ClassWithMemberFunction> {
11197
AlwaysIterator() : size_(0), n_(0) {}
11298
AlwaysIterator(difference_type size, difference_type n) : size_(size), n_(n) {}
11399

0 commit comments

Comments
 (0)