[PATCH] D113799: ADT: Fix const-correctness of iterator facade
Duncan P. N. Exon Smith via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 12 12:52:10 PST 2021
dexonsmith updated this revision to Diff 386929.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D113799/new/
https://reviews.llvm.org/D113799
Files:
llvm/include/llvm/ADT/iterator.h
llvm/unittests/ADT/IteratorTest.cpp
Index: llvm/unittests/ADT/IteratorTest.cpp
===================================================================
--- llvm/unittests/ADT/IteratorTest.cpp
+++ llvm/unittests/ADT/IteratorTest.cpp
@@ -81,6 +81,14 @@
using IntProxyIterator = PointerProxyWrapper<int, IntProxy>;
using ConstIntProxyIterator = PointerProxyWrapper<const int, ConstIntProxy>;
+// There should only be a single (const-qualified) operator*, operator->, and
+// operator[]. This test confirms that there isn't a non-const overload. Rather
+// than adding those, users should double-check that T, PointerT, and ReferenceT
+// have the right constness, and/or make fields mutable.
+static_assert(&IntIterator::operator* == &IntIterator::operator*, "");
+static_assert(&IntIterator::operator-> == &IntIterator::operator->, "");
+static_assert(&IntIterator::operator[] == &IntIterator::operator[], "");
+
template <class T,
std::enable_if_t<std::is_assignable<T, int>::value, bool> = false>
constexpr bool canAssignFromInt(T &&) {
Index: llvm/include/llvm/ADT/iterator.h
===================================================================
--- llvm/include/llvm/ADT/iterator.h
+++ llvm/include/llvm/ADT/iterator.h
@@ -35,6 +35,21 @@
/// terms of addition of one. These aren't equivalent for all iterator
/// categories, and respecting that adds a lot of complexity for little gain.
///
+/// Iterators are expected to have const rules analogous to pointers, with a
+/// single, const-qualified operator*() that returns ReferenceT. This matches
+/// the second and third pointers in the following example:
+/// \code
+/// int Value;
+/// { int *I = &Value; } // ReferenceT 'int&'
+/// { int *const I = &Value; } // ReferenceT 'int&'; const
+/// { const int *I = &Value; } // ReferenceT 'const int&'
+/// { const int *const I = &Value; } // ReferenceT 'const int&'; const
+/// \endcode
+/// If an iterator facade returns a handle to its own state, then T (and
+/// PointerT and ReferenceT) should usually be const-qualified. Otherwise, if
+/// clients are expected to modify the handle itself, the field can be declared
+/// mutable or use const_cast.
+///
/// Classes wishing to use `iterator_facade_base` should implement the following
/// methods:
///
@@ -187,17 +202,9 @@
return !(static_cast<const DerivedT &>(*this) < RHS);
}
- PointerProxy operator->() {
- return static_cast<DerivedT *>(this)->operator*();
- }
PointerProxy operator->() const {
return static_cast<const DerivedT *>(this)->operator*();
}
- ReferenceProxy operator[](DifferenceTypeT n) {
- static_assert(IsRandomAccess,
- "Subscripting is only defined for random access iterators.");
- return static_cast<DerivedT *>(this)->operator+(n);
- }
ReferenceProxy operator[](DifferenceTypeT n) const {
static_assert(IsRandomAccess,
"Subscripting is only defined for random access iterators.");
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D113799.386929.patch
Type: text/x-patch
Size: 2956 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20211112/d19cac76/attachment.bin>
More information about the llvm-commits
mailing list