[range.utility.conv] (original) (raw)
25 Ranges library [ranges]
25.5 Range utilities [range.utility]
25.5.7 Range conversions [range.utility.conv]
25.5.7.1 General [range.utility.conv.general]
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.
ranges::to is applied recursively, allowing the conversion of a range of ranges.
[Example 1: string_view str = "the quick brown fox";auto words = views::split(str, ' ') | to<vector<string>>(); — _end example_]
Let reservable-container be defined as follows:template<class Container> constexpr bool reservable-container = sized_range<Container> && requires(Container& c, range_size_t<Container> n) { c.reserve(n);{ c.capacity() } -> same_as<decltype(n)>;{ c.max_size() } -> same_as<decltype(n)>;};
Let container-appendable be defined as follows:template<class Container, class Ref> constexpr bool container-appendable = 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)); });};
Let container-append be defined as follows:template<class Container> constexpr auto container-append(Container& c) { 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 ranges::to [range.utility.conv.to]
template<class C, [input_range](range.refinements#concept:input%5Frange "25.4.5 Other range refinements [range.refinements]") R, class... Args> requires (<C>) constexpr C to(R&& r, Args&&... args);
Mandates: C is a cv-unqualified class type.
Returns: An object of type Cconstructed from the elements of r in the following manner:
- If C does not satisfy input_range orconvertible_to<range_reference_t<R>, range_value_t<C>>is true:
- If constructible_from<C, R, Args...> is true:C(std::forward<R>(r), std::forward<Args>(args)...)
- Otherwise, ifconstructible_from<C, from_range_t, R, Args...>is true:C(from_range, std::forward<R>(r), std::forward<Args>(args)...)
- Otherwise, if
* common_range<R> is true,
* the qualified-id iterator_traits<iterator_t<R>>::iterator_categoryis valid and denotes a type that modelsderived_from<input_iterator_tag>, and
* constructible_from<C, iterator_t<R>, sentinel_t<R>, Args...>is true:
C(ranges::begin(r), ranges::end(r), std::forward<Args>(args)...)
- Otherwise, if
* constructible_from<C, Args...> is true, and
* container-appendable<C, range_reference_t<R>> is true:
C c(std::forward<Args>(args)...);if constexpr (approximately_sized_range<R> && reservable-container<C>) c.reserve(static_cast<range_size_t<C>>(ranges::reserve_hint(r))); ranges::for_each(r, container-append(c));
- Otherwise, the program is ill-formed.
- Otherwise, if input_range<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)...);
- Otherwise, the program is ill-formed.
template<template<class...> class C, [input_range](range.refinements#concept:input%5Frange "25.4.5 Other range refinements [range.refinements]") R, class... Args> constexpr auto to(R&& r, Args&&... args);
Let input-iterator be an exposition-only type:struct input-iterator { 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:
input-iterator meets the syntactic requirements of Cpp17InputIterator.
— _end note_]
Let DEDUCE_EXPR be defined as follows:
- C(declval<R>(), declval<Args>()...) if that is a valid expression,
- otherwise, C(from_range, declval<R>(), declval<Args>()...)if that is a valid expression,
- otherwise,C(declval<_input-iterator_>(), declval<_input-iterator_>(), declval<Args>()...) if that is a valid expression,
- otherwise, the program is ill-formed.
Returns: to<decltype(_DEDUCE_EXPR_)>(std::forward<R>(r), std::forward<Args>(args)...).
25.5.7.3 ranges::to adaptors [range.utility.conv.adaptors]
template<class C, class... Args> requires (<C>) constexpr auto to(Args&&... args);template<template<class...> class C, class... Args> constexpr auto to(Args&&... args);
Mandates: For the first overload,C is a cv-unqualified class type.
Returns: A range adaptor closure object ([range.adaptor.object]) fthat is a perfect forwarding call wrapper ([func.require]) with the following properties: