Skip to content

Commit 1bfe5b1

Browse files
cpplearnerCaseyCarterStephanTLavavej
authored
Repairing counted_iterator (#1939)
Co-authored-by: Casey Carter <[email protected]> Co-authored-by: Stephan T. Lavavej <[email protected]>
1 parent 4449d8a commit 1bfe5b1

File tree

4 files changed

+77
-20
lines changed

4 files changed

+77
-20
lines changed

stl/inc/iterator

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,10 +1038,35 @@ struct iterator_traits<common_iterator<_Iter, _Se>> {
10381038
};
10391039

10401040
// CLASS TEMPLATE counted_iterator
1041+
template <class _Iter>
1042+
struct _Counted_iterator_value_type_base {};
1043+
1044+
template <indirectly_readable _Iter>
1045+
struct _Counted_iterator_value_type_base<_Iter> {
1046+
using value_type = iter_value_t<_Iter>;
1047+
};
1048+
1049+
template <class _Iter>
1050+
struct _Counted_iterator_category_base : _Counted_iterator_value_type_base<_Iter> {};
1051+
1052+
template <_Has_member_iterator_category _Iter>
1053+
struct _Counted_iterator_category_base<_Iter> : _Counted_iterator_value_type_base<_Iter> {
1054+
using iterator_category = typename _Iter::iterator_category;
1055+
};
1056+
1057+
template <class _Iter>
1058+
struct _Counted_iterator_concept_base : _Counted_iterator_category_base<_Iter> {};
1059+
1060+
template <_Has_member_iterator_concept _Iter>
1061+
struct _Counted_iterator_concept_base<_Iter> : _Counted_iterator_category_base<_Iter> {
1062+
using iterator_concept = typename _Iter::iterator_concept;
1063+
};
1064+
10411065
template <input_or_output_iterator _Iter>
1042-
class counted_iterator {
1066+
class counted_iterator : public _Counted_iterator_concept_base<_Iter> {
10431067
public:
1044-
using iterator_type = _Iter;
1068+
using iterator_type = _Iter;
1069+
using difference_type = iter_difference_t<_Iter>;
10451070

10461071
// [counted.iter.const]
10471072
constexpr counted_iterator() requires default_initializable<_Iter> = default;
@@ -1099,6 +1124,10 @@ public:
10991124
return *_Current;
11001125
}
11011126

1127+
_NODISCARD constexpr auto operator->() const noexcept requires contiguous_iterator<_Iter> {
1128+
return _STD to_address(_Current);
1129+
}
1130+
11021131
_NODISCARD constexpr decltype(auto) operator[](const iter_difference_t<_Iter> _Diff) const
11031132
requires random_access_iterator<_Iter> {
11041133
#if _ITERATOR_DEBUG_LEVEL != 0
@@ -1323,25 +1352,12 @@ private:
13231352
iter_difference_t<_Iter> _Length = 0;
13241353
};
13251354

1326-
template <class _Iter>
1327-
struct incrementable_traits<counted_iterator<_Iter>> {
1328-
using difference_type = iter_difference_t<_Iter>;
1329-
};
1330-
1355+
// clang-format off
13311356
template <input_iterator _Iter>
1357+
requires (!_Is_from_primary<iterator_traits<_Iter>>)
13321358
struct iterator_traits<counted_iterator<_Iter>> : iterator_traits<_Iter> {
1333-
using pointer = void;
1334-
};
1335-
1336-
template <contiguous_iterator _Iter>
1337-
struct pointer_traits<counted_iterator<_Iter>> { // TRANSITION, address LWG-3408 and include this
1338-
using pointer = counted_iterator<_Iter>;
1339-
using element_type = remove_reference_t<iter_reference_t<_Iter>>;
1340-
using difference_type = iter_difference_t<_Iter>;
1341-
1342-
_NODISCARD static constexpr element_type* to_address(const pointer _It) noexcept {
1343-
return _STD to_address(_It.base());
1344-
}
1359+
// clang-format on
1360+
using pointer = conditional_t<contiguous_iterator<_Iter>, add_pointer_t<iter_reference_t<_Iter>>, void>;
13451361
};
13461362
#endif // __cpp_lib_concepts
13471363

stl/inc/yvals_core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@
245245
// P2102R0 Making "Implicit Expression Variations" More Explicit
246246
// P2106R0 Range Algorithm Result Types
247247
// P2116R0 Removing tuple-Like Protocol Support From Fixed-Extent span
248+
// P2259R1 Repairing Input Range Adaptors And counted_iterator
249+
// (partially implemented)
248250
// P2325R3 Views Should Not Be Required To Be Default Constructible
249251
// P????R? directory_entry::clear_cache()
250252

tests/std/tests/P0896R4_common_iterator/test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ bool test_operator_arrow() {
189189
assert(*countedIter == P(0, 1));
190190
assert(countedIter->first == 0);
191191
assert(countedIter->second == 1);
192-
static_assert(is_same_v<decltype(countedIter.operator->()), P*>);
192+
static_assert(is_same_v<decltype(countedIter.operator->()), counted_iterator<P*> const&>);
193193

194194
return true;
195195
}

tests/std/tests/P0896R4_counted_iterator/test.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,43 @@ struct instantiator {
305305
}
306306
};
307307

308+
// Also test P2259R1 Repairing input range adaptors and counted_iterator
309+
struct simple_forward_iter {
310+
using value_type = double;
311+
using difference_type = long;
312+
using iterator_category = input_iterator_tag;
313+
using iterator_concept = forward_iterator_tag;
314+
315+
value_type operator*() const;
316+
simple_forward_iter& operator++();
317+
simple_forward_iter operator++(int);
318+
319+
bool operator==(const simple_forward_iter&) const;
320+
};
321+
322+
using CI = counted_iterator<simple_forward_iter>;
323+
324+
static_assert(same_as<iterator_traits<simple_forward_iter>::iterator_category, input_iterator_tag>);
325+
static_assert(forward_iterator<simple_forward_iter>);
326+
static_assert(forward_iterator<CI>);
327+
static_assert(!contiguous_iterator<CI>);
328+
static_assert(same_as<CI::value_type, double>);
329+
static_assert(same_as<CI::difference_type, long>);
330+
static_assert(same_as<CI::iterator_category, input_iterator_tag>);
331+
static_assert(same_as<CI::iterator_concept, forward_iterator_tag>);
332+
333+
void test_P2259() {
334+
struct A {
335+
int m;
336+
};
337+
A a[2] = {{1}, {2}};
338+
counted_iterator ci{a, 2};
339+
reverse_iterator ri{ci + 1};
340+
static_assert(contiguous_iterator<decltype(ci)>);
341+
assert(ci->m == 1);
342+
assert(ri->m == 1);
343+
}
344+
308345
int main() {
309346
STATIC_ASSERT((with_writable_iterators<instantiator, int>::call(), true));
310347
with_writable_iterators<instantiator, int>::call();
@@ -317,4 +354,6 @@ int main() {
317354
_Seek_wrapped(ci, uci);
318355
assert((ci == counted_iterator{ranges::next(lst.begin()), 1}));
319356
}
357+
358+
test_P2259();
320359
}

0 commit comments

Comments
 (0)