[readable.traits]

# 24 Iterators library [[iterators]](./#iterators)

## 24.3 Iterator requirements [[iterator.requirements]](iterator.requirements#readable.traits)

### 24.3.2 Associated types [[iterator.assoc.types]](iterator.assoc.types#readable.traits)

#### 24.3.2.2 Indirectly readable traits [readable.traits]

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L808)

To implement algorithms only in terms of indirectly readable types,
it is often necessary
to determine the value type that corresponds to
a particular indirectly readable type[.](#1.sentence-1)

Accordingly, it is required that if R is the name of a type that
models the [indirectly_readable](iterator.concept.readable#concept:indirectly_readable "24.3.4.2 Concept indirectly_­readable [iterator.concept.readable]") concept ([[iterator.concept.readable]](iterator.concept.readable "24.3.4.2 Concept indirectly_­readable")),
the typeiter_value_t<R> be defined as the indirectly readable type's value type[.](#1.sentence-2)

[ð](#lib:indirectly_readable_traits)

template<class> struct *cond-value-type* { }; // *exposition only*template<class T>requires is_object_v<T>struct *cond-value-type*<T> {using value_type = remove_cv_t<T>;};

template<class T>concept [*has-member-value-type*](#concept:has-member-value-type "24.3.2.2 Indirectly readable traits [readable.traits]") = requires { typename T::value_type; }; // *exposition only*template<class T>concept [*has-member-element-type*](#concept:has-member-element-type "24.3.2.2 Indirectly readable traits [readable.traits]") = requires { typename T::element_type; }; // *exposition only*template<class> struct indirectly_readable_traits { };

template<class T>struct indirectly_readable_traits<T*>: *cond-value-type*<T> { };

template<class I>requires is_array_v<I>struct indirectly_readable_traits<I> {using value_type = remove_cv_t<remove_extent_t<I>>;};

template<class I>struct indirectly_readable_traits<const I>: indirectly_readable_traits<I> { };

template<[*has-member-value-type*](#concept:has-member-value-type "24.3.2.2 Indirectly readable traits [readable.traits]") T>struct indirectly_readable_traits<T>: *cond-value-type*<typename T::value_type> { };

template<[*has-member-element-type*](#concept:has-member-element-type "24.3.2.2 Indirectly readable traits [readable.traits]") T>struct indirectly_readable_traits<T>: *cond-value-type*<typename T::element_type> { };

template<[*has-member-value-type*](#concept:has-member-value-type "24.3.2.2 Indirectly readable traits [readable.traits]") T>requires [*has-member-element-type*](#concept:has-member-element-type "24.3.2.2 Indirectly readable traits [readable.traits]")<T>struct indirectly_readable_traits<T> { };

template<[*has-member-value-type*](#concept:has-member-value-type "24.3.2.2 Indirectly readable traits [readable.traits]") T>requires [*has-member-element-type*](#concept:has-member-element-type "24.3.2.2 Indirectly readable traits [readable.traits]")<T> &&[same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<remove_cv_t<typename T::element_type>, remove_cv_t<typename T::value_type>>struct indirectly_readable_traits<T>: *cond-value-type*<typename T::value_type> { };

template<class T> using iter_value_t = *see below*;

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L874)

Let RI be remove_cvref_t<I>[.](#2.sentence-1)

The type iter_value_t<I> denotes

- [(2.1)](#2.1)

indirectly_readable_traits<RI>​::​value_type if iterator_traits<RI> names a specialization
generated from the primary template, and

- [(2.2)](#2.2)

iterator_traits<RI>​::​value_type otherwise[.](#2.sentence-2)

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L887)

Class template indirectly_readable_traits may be specialized
on program-defined types[.](#3.sentence-1)

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L891)

[*Note [1](#note-1)*:

Some legacy output iterators define a nested type named value_type that is an alias for void[.](#4.sentence-1)

These types are not [indirectly_readable](iterator.concept.readable#concept:indirectly_readable "24.3.4.2 Concept indirectly_­readable [iterator.concept.readable]") and have no associated value types[.](#4.sentence-2)

â *end note*]

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L899)

[*Note [2](#note-2)*:

Smart pointers like shared_ptr<int> are [indirectly_readable](iterator.concept.readable#concept:indirectly_readable "24.3.4.2 Concept indirectly_­readable [iterator.concept.readable]") and
have an associated value type, but a smart pointer like shared_ptr<void> is not [indirectly_readable](iterator.concept.readable#concept:indirectly_readable "24.3.4.2 Concept indirectly_­readable [iterator.concept.readable]") and has no associated value type[.](#5.sentence-1)

â *end note*]
