[libcxx-commits] [libcxx] [libc++] Implement LWG3601: `common_iterator`'s postfix-proxy needs `indirectly_readable` (PR #237574)

A. Jiang via libcxx-commits libcxx-commits at lists.llvm.org
Mon Nov 2 19:07:31 PST 2026


================
@@ -121,6 +121,28 @@ class value_type_not_move_constructible_iterator
     constexpr void operator++(int) {++(*this);}
 };
 
+// Not indirectly_readable: operator* is non-const. Postfix ++ returns void, so *it++ is ill-formed.
+template <class It>
+class non_const_deref_iterator {
+  It it_;
+
+public:
+  using value_type      = std::iter_value_t<It>;
+  using difference_type = std::iter_difference_t<It>;
+
+  friend constexpr It base(const non_const_deref_iterator& i) { return i.it_; }
+
+  explicit constexpr non_const_deref_iterator(It it) : it_(it) {}
+
+  constexpr decltype(auto) operator*() { return *it_; }
+
+  constexpr non_const_deref_iterator& operator++() {
+    ++it_;
+    return *this;
+  }
+  constexpr void operator++(int) { ++it_; }
+};
----------------
frederick-vs-ja wrote:

I'm afraid that such non-const `operator*` possibly violates some (no diagnostic required) requirements on implicit expression variations ([[concepts.equality]](https://eel.is/c++draft/concepts.equality)). But given missing const `operator*` is already diagnosed so this is possibly fine.

How about also testing the following weird but less risky (to me) type? [Godbolt link](https://godbolt.org/z/bMEs3dsnj).

```C++
// Not indirectly_readable since iter_move returns void; Postfix ++ returns void, so *it++ is ill-formed.
template <class It>
class non_iter_movable_iterator {
  It it_;

public:
  using value_type      = std::iter_value_t<It>;
  using difference_type = std::iter_difference_t<It>;

  friend constexpr It base(const non_iter_movable_iterator& i) { return i.it_; }

  explicit constexpr non_iter_movable_iterator(It it) : it_(it) {}

  constexpr decltype(auto) operator*() const { return *it_; }

  constexpr non_iter_movable_iterator& operator++() {
    ++it_;
    return *this;
  }
  constexpr void operator++(int) { ++it_; }

  friend constexpr void iter_move(const non_iter_movable_iterator&) {}
};
```

https://github.com/llvm/llvm-project/pull/237574


More information about the libcxx-commits mailing list