[range.utility.conv]

# 25 Ranges library [[ranges]](./#ranges)

## 25.5 Range utilities [[range.utility]](range.utility#conv)

### 25.5.7 Range conversions [range.utility.conv]

#### [25.5.7.1](#general) General [[range.utility.conv.general]](range.utility.conv.general)

[1](#general-1)

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

The range conversion functions construct
an object (usually a container) from a range,
by using a constructor taking a range,
a from_range_t tagged constructor, or
a constructor taking a pair of iterators, or
by inserting each element of the range into the default-constructed object[.](#general-1.sentence-1)

[2](#general-2)

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

ranges​::​to is applied recursively,
allowing the conversion of a range of ranges[.](#general-2.sentence-1)

[*Example [1](#general-example-1)*: string_view str = "the quick brown fox";auto words = views::split(str, ' ') | to<vector<string>>();// words is vector<string>{"the", "quick", "brown", "fox"} â *end example*]

[3](#general-3)

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

Let *reservable-container* be defined as follows:template<class Container>constexpr bool *reservable-container* = // *exposition only*[sized_range](range.sized#concept:sized_range "25.4.4 Sized ranges [range.sized]")<Container> &&requires(Container& c, range_size_t<Container> n) { c.reserve(n); { c.capacity() } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<decltype(n)>; { c.max_size() } -> [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<decltype(n)>; };

[4](#general-4)

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

Let *container-appendable* be defined as follows:template<class Container, class Ref>constexpr bool *container-appendable* = // *exposition only*requires(Container& c, Ref&& ref) {requires (requires { c.emplace_back(std::forward<Ref>(ref)); } ||requires { c.push_back(std::forward<Ref>(ref)); } ||requires { c.emplace(c.end(), std::forward<Ref>(ref)); } ||requires { c.insert(c.end(), std::forward<Ref>(ref)); }); };

[5](#general-5)

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

Let *container-append* be defined as follows:template<class Container>constexpr auto *container-append*(Container& c) { // *exposition only*return [&c]<class Ref>(Ref&& ref) {if constexpr (requires { c.emplace_back(declval<Ref>()); }) c.emplace_back(std::forward<Ref>(ref)); else if constexpr (requires { c.push_back(declval<Ref>()); }) c.push_back(std::forward<Ref>(ref)); else if constexpr (requires { c.emplace(c.end(), declval<Ref>()); }) c.emplace(c.end(), std::forward<Ref>(ref)); else c.insert(c.end(), std::forward<Ref>(ref)); };}

#### [25.5.7.2](#to) ranges​::​to [[range.utility.conv.to]](range.utility.conv.to)

[ð](#lib:to,ranges)

`template<class C, [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") R, class... Args> requires (![view](range.view#concept:view "25.4.5 Views [range.view]")<C>)
  constexpr C to(R&& r, Args&&... args);
`

[1](#to-1)

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

*Mandates*: C is a cv-unqualified class type[.](#to-1.sentence-1)

[2](#to-2)

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

*Returns*: An object of type C constructed from the elements of r in the following manner:

- [(2.1)](#to-2.1)

  If C does not satisfy [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") or[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_­to [concept.convertible]")<range_reference_t<R>, range_value_t<C>> is true:
  * [(2.1.1)](#to-2.1.1)

If [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")<C, R, Args...> is true:C(std::forward<R>(r), std::forward<Args>(args)...)

  * [(2.1.2)](#to-2.1.2)

Otherwise, if[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")<C, from_range_t, R, Args...> is true:C(from_range, std::forward<R>(r), std::forward<Args>(args)...)

  * [(2.1.3)](#to-2.1.3)

Otherwise, if
    +
          [(2.1.3.1)](#to-2.1.3.1)
[common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<R> is true,

    +
          [(2.1.3.2)](#to-2.1.3.2)
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]")iterator_traits<iterator_t<R>>​::​iterator_category is valid and denotes a type that models[derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_­from [concept.derived]")<input_iterator_tag>, and

    +
          [(2.1.3.3)](#to-2.1.3.3)
[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")<C, iterator_t<R>, sentinel_t<R>, Args...> is true:

C(ranges::begin(r), ranges::end(r), std::forward<Args>(args)...)

  * [(2.1.4)](#to-2.1.4)

Otherwise, if
    +
          [(2.1.4.1)](#to-2.1.4.1)
[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")<C, Args...> is true, and

    +
          [(2.1.4.2)](#to-2.1.4.2)
*container-appendable*<C, range_reference_t<R>> is true:

C c(std::forward<Args>(args)...);if constexpr ([approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3 Approximately sized ranges [range.approximately.sized]")<R> && *reservable-container*<C>) c.reserve(static_cast<range_size_t<C>>(ranges::reserve_hint(r)));
ranges::for_each(r, *container-append*(c));

  * [(2.1.5)](#to-2.1.5)

Otherwise, the program is ill-formed[.](#to-2.1.sentence-1)

- [(2.2)](#to-2.2)

  Otherwise,
if [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<R>> is true:to<C>(ref_view(r) | views::transform([](auto&& elem) {return to<range_value_t<C>>(std::forward<decltype(elem)>(elem));}), std::forward<Args>(args)...);

- [(2.3)](#to-2.3)

  Otherwise, the program is ill-formed[.](#to-2.3.sentence-1)

[ð](#lib:to,ranges_)

`template<template<class...> class C, [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") R, class... Args>
  constexpr auto to(R&& r, Args&&... args);
`

[3](#to-3)

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

Let *input-iterator* be an exposition-only type:struct *input-iterator* { // *exposition only*using iterator_category = input_iterator_tag; using value_type = range_value_t<R>; using difference_type = ptrdiff_t; using pointer = add_pointer_t<range_reference_t<R>>; using reference = range_reference_t<R>;
 reference operator*() const;
 pointer operator->() const; *input-iterator*& operator++(); *input-iterator* operator++(int); bool operator==(const *input-iterator*&) const;};

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

*input-iterator* meets
the syntactic requirements of *Cpp17InputIterator*[.](#to-3.sentence-1)

â *end note*]

[4](#to-4)

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

Let *DEDUCE_EXPR* be defined as follows:

- [(4.1)](#to-4.1)

C(declval<R>(), declval<Args>()...) if that is a valid expression,

- [(4.2)](#to-4.2)

otherwise, C(from_range, declval<R>(), declval<Args>()...) if that is a valid expression,

- [(4.3)](#to-4.3)

otherwise,C(declval<*input-iterator*>(), declval<*input-iterator*>(), declval<Args>()...) if that is a valid expression,

- [(4.4)](#to-4.4)

otherwise, the program is ill-formed[.](#to-4.sentence-1)

[5](#to-5)

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

*Returns*: to<decltype(*DEDUCE_EXPR*)>(std​::​forward<R>(r), std​::​forward<Args>(args)...)[.](#to-5.sentence-1)

#### [25.5.7.3](#adaptors) ranges​::​to adaptors [[range.utility.conv.adaptors]](range.utility.conv.adaptors)

[ð](#lib:to,ranges__)

`template<class C, class... Args> requires (![view](range.view#concept:view "25.4.5 Views [range.view]")<C>)
  constexpr auto to(Args&&... args);
template<template<class...> class C, class... Args>
  constexpr auto to(Args&&... args);
`

[1](#adaptors-1)

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

*Mandates*: For the first overload,C is a cv-unqualified class type[.](#adaptors-1.sentence-1)

[2](#adaptors-2)

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

*Returns*: A range adaptor closure object ([[range.adaptor.object]](range.adaptor.object "25.7.2 Range adaptor objects")) f that is a perfect forwarding call wrapper ([[func.require]](func.require#term.perfect.forwarding.call.wrapper "22.10.4 Requirements"))
with the following properties:

- [(2.1)](#adaptors-2.1)

  It has no target object[.](#adaptors-2.1.sentence-1)

- [(2.2)](#adaptors-2.2)

  Its bound argument entities bound_args consist of
objects of types decay_t<Args>... direct-non-list-initialized with std​::​forward<Args>(args)...,
respectively[.](#adaptors-2.2.sentence-1)

- [(2.3)](#adaptors-2.3)

  Its call pattern is to<C>(r, bound_args...),
where r is the argument used in a function call expression of f[.](#adaptors-2.3.sentence-1)
