1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
From c33967fcbc838e1a36e8ad7665d1b73177716e9d Mon Sep 17 00:00:00 2001
From: Protobuf Team Bot <protobuf-github-bot@google.com>
Date: Mon, 20 Nov 2023 04:18:49 -0800
Subject: [PATCH] Add iterator_concept support.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This allows for better code generation in C++20 for algorithms that take advantage of random access vs contiguous data.
```
name old INSTRUCTIONS/op new INSTRUCTIONS/op delta
BM_RepeatedField_Sort 5.74k ± 0% 5.74k ± 0% -0.13% (p=0.000 n=179+183)
BM_RepeatedField_ToVector 693 ± 0% 693 ± 0% ~ (p=0.153 n=93+91)
BM_RepeatedPtrField_SortIndirect 562 ± 0% 559 ± 0% -0.53% (p=0.000 n=92+92)
```
PiperOrigin-RevId: 583983215
---
src/google/protobuf/BUILD.bazel | 1 +
src/google/protobuf/repeated_field.h | 18 +++--
.../protobuf/repeated_field_unittest.cc | 69 +++++++++++++++++++
src/google/protobuf/repeated_ptr_field.h | 26 +++++--
4 files changed, 103 insertions(+), 11 deletions(-)
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index a3f77153289b..5351846558e6 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -1035,14 +1035,18 @@ namespace internal {
// the compiler isn't allowed to inline them.
template <typename Element>
class RepeatedIterator {
+ private:
+ using traits =
+ std::iterator_traits<typename std::remove_const<Element>::type*>;
+
public:
- using iterator_category = std::random_access_iterator_tag;
- // Note: remove_const is necessary for std::partial_sum, which uses value_type
- // to determine the summation variable type.
- using value_type = typename std::remove_const<Element>::type;
- using difference_type = std::ptrdiff_t;
+ // Note: value_type is never cv-qualified.
+ using value_type = typename traits::value_type;
+ using difference_type = typename traits::difference_type;
using pointer = Element*;
using reference = Element&;
+ using iterator_category = typename traits::iterator_category;
+ using iterator_concept = typename IteratorConceptSupport<traits>::tag;
constexpr RepeatedIterator() noexcept : it_(nullptr) {}
@@ -1142,10 +1146,10 @@ class RepeatedIterator {
// Allow construction from RepeatedField.
friend class RepeatedField<value_type>;
- explicit RepeatedIterator(Element* it) noexcept : it_(it) {}
+ explicit RepeatedIterator(pointer it) noexcept : it_(it) {}
// The internal iterator.
- Element* it_;
+ pointer it_;
};
// A back inserter for RepeatedField objects.
diff --git a/src/google/protobuf/repeated_ptr_field.h b/src/google/protobuf/repeated_ptr_field.h
index 64cdd1890e3c..7a57dfee134c 100644
@@ -1852,6 +1853,17 @@ class RepeatedPtrIterator {
void* const* it_;
};
+template <typename Traits, typename = void>
+struct IteratorConceptSupport {
+ using tag = typename Traits::iterator_category;
+};
+
+template <typename Traits>
+struct IteratorConceptSupport<Traits,
+ std::void_t<typename Traits::iterator_concept>> {
+ using tag = typename Traits::iterator_concept;
+};
+
// Provides an iterator that operates on pointers to the underlying objects
// rather than the objects themselves as RepeatedPtrIterator does.
// Consider using this when working with stl algorithms that change
@@ -1861,13 +1873,19 @@ class RepeatedPtrIterator {
// iterator, or "const void* const" for a constant iterator.
template <typename Element, typename VoidPtr>
class RepeatedPtrOverPtrsIterator {
+ private:
+ using traits =
+ std::iterator_traits<typename std::remove_const<Element>::type*>;
+
public:
- using iterator = RepeatedPtrOverPtrsIterator<Element, VoidPtr>;
- using iterator_category = std::random_access_iterator_tag;
- using value_type = typename std::remove_const<Element>::type;
- using difference_type = std::ptrdiff_t;
+ using value_type = typename traits::value_type;
+ using difference_type = typename traits::difference_type;
using pointer = Element*;
using reference = Element&;
+ using iterator_category = typename traits::iterator_category;
+ using iterator_concept = typename IteratorConceptSupport<traits>::tag;
+
+ using iterator = RepeatedPtrOverPtrsIterator<Element, VoidPtr>;
RepeatedPtrOverPtrsIterator() : it_(nullptr) {}
explicit RepeatedPtrOverPtrsIterator(VoidPtr* it) : it_(it) {}
|