[libcxx-commits] [libcxx] [libc++] Merge the private iterator_traits aliases with their ranges versions (PR #162661)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Wed Oct 15 08:44:01 PDT 2025


================
@@ -71,15 +65,9 @@ struct _ClassicAlgPolicy {};
 
 template <>
 struct _IterOps<_ClassicAlgPolicy> {
-  template <class _Iter>
-  using __value_type _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::value_type;
----------------
ldionne wrote:

Your proofs:

1. For `iter_reference_t`, https://eel.is/c++draft/iterator.cpp17#input.iterators-2 says that `*a` must be `iterator_traits::reference` for a C++17 iterator. Hence `iterator_traits::reference` and `decltype(*a) == iter_reference_t<It>` must be the same. ✅

2. For `iter_difference_t`, we have two cases. If `iterator_traits<It>` is specialized, [incrementable.traits](https://eel.is/c++draft/incrementable.traits#2.2) says that `iter_difference_t<It>` is `iterator_traits<It>::difference_type`. If [not specialized](https://eel.is/c++draft/incrementable.traits#2.1), then `iter_difference_t<It>` is `incrementable_traits<It>::difference_type`, whatever that is. However, in C++20, `iterator_traits` *also* changed to be more C++20 friendly (I guess):
    - if `It::difference_type` and `It::value_type` and `It::reference` (etc..) *do* exist, then `iterator_traits<It>::difference_type` is `It::difference_type`. However, in that case, `incrementable_traits<It>::difference_type` [is also](https://eel.is/c++draft/incrementable.traits) `It::difference_type`, **unless** it is specialized explicitly. And it's legal to [specialize it explicitly](https://eel.is/c++draft/incrementable.traits#3). This means that technically, if someone specializes `incrementable_traits<It>` to give it a `difference_type` that doesn't match `iterator_traits<It>::difference_type`, this patch will produce a difference. It's unclear whether
        > Users may specialize incrementable_traits on program-defined types[.](https://eel.is/c++draft/incrementable.traits#3.sentence-1)

      is intended to override the normal requirement that specializations must be equivalent to the base template. This is probably material for a quick LWG issue. ❌
    - if `It::difference_type` or any of its friends do not exist, `iterator_traits<It>::difference_type` is defined to be `incrementable_traits<It>::difference_type`, so the equivalence holds. ✅
    

3. For `iter_value_t`, `iter_value_t<It>` is `iterator_traits<It>::value_type` if `iterator_traits<It>` [is specialized](https://eel.is/c++draft/iterator.requirements#readable.traits-2). Otherwise, it is `indirectly_readable_traits<It>::value_type`, whatever that is. However,
    - if `It::difference_type` and `It::value_type` and `It::reference` (etc..) *do* exist, then `iterator_traits<It>::value_type` [is](https://eel.is/c++draft/iterator.assoc.types#iterator.traits-3.1) `I::value_type`. And in that case `indirectly_readable_traits<It>::value_type` is [a rather complicated thing](https://eel.is/c++draft/readable.traits#1). It seems that if `It::element_type` and `It::value_type` disagree, `indirectly_readable_traits<It>::value_type` would not be defined whereas `iterator_traits<It>::value_type` would be. There's also the specialization problem above. And there's the issue of legacy output iterators where `It::value_type == void`, as explained in [this note](https://eel.is/c++draft/readable.traits#4). ❌
    - if `It::value_type` or any of its friends do not exist, `iterator_traits<It>::value_type` [is defined](https://eel.is/c++draft/iterator.assoc.types#iterator.traits-3.2) to `indirectly_readable_traits<It>::value_type`. ✅

So, in summary, I think we have the following issues:
- `iterator_traits<It>::difference_type` may be `It::difference_type` but `incrementable_traits<It>` may be something else via a specialization
- `iterator_traits<It>::value_type` may be `It::value_type` but `indirectly_readable_traits<It>::value_type` does not exist
- `iterator_traits<It>::value_type` may be `It::value_type` but `indirectly_readable_traits<It>` may be specialized
- `iterator_traits<It>::value_type` may be `It::value_type == void` but `indirectly_readable_traits<It>` does not exist

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


More information about the libcxx-commits mailing list