std::ranges::to - cppreference.com (original) (raw)

Defined in header
template< class C, ranges::input_range R, class... Args > requires (ranges::view<C>) constexpr C to( R&& r, Args&&... args ); (1) (since C++23)
template< template< class... > class C, ranges::input_range R, class... Args > constexpr auto to( R&& r, Args&&... args ); (2) (since C++23)
template< class C, class... Args > requires (ranges::view<C>) constexpr /*range adaptor closure*/ to( Args&&... args ); (3) (since C++23)
template< template< class... > class C, class... Args > constexpr /*range adaptor closure*/ to( Args&&... args ); (4) (since C++23)
Helper templates
template< class Container > constexpr bool /*reservable-container*/ = ranges::sized_range<Container> && requires (Container& c, ranges::range_size_t<Container> n) { c.reserve(n); { c.capacity() } -> std::same_as<decltype(n)>; { c.max_size() } -> std::same_as<decltype(n)>; }; (5) (exposition only*)
template< class Container, class Reference > constexpr bool /*container-appendable*/ = requires (Container& c, Reference&& ref) { requires ( requires { c.emplace_back(std::forward<Reference>(ref)); } | requires { c.push_back(std::forward<Reference>(ref)); } requires { c.emplace(c.end(), std::forward<Reference>(ref)); }
template< class Reference, class C > constexpr auto /*container-appender*/( C& c ); (7) (exposition only*)
template< class R, class T > concept /*container-compatible-range*/ = ranges::input_range<R> && std::convertible_to<ranges::range_reference_t<R>, T>; (8) (exposition only*)

The overloads of the range conversion function construct a new non-view object from a source range as its first argument by calling a constructor taking a range, a std::from_range_t tagged ranged constructor, a constructor taking an iterator-sentinel pair, or by back inserting each element of the source range into the arguments-constructed object.

  1. Constructs an object of type C from the elements of r in the following:

  2. Constructing a non-view object as if direct-initializing (but not direct-list-initializing) an object of type C from the source range std::forward<R>(r) and the rest of the functional arguments std::forward<Args>(args)... if std::constructible_from<C, R, Args...> is true.

  3. Otherwise, constructing a non-view range object as if direct-initializing (but not direct-list-initializing) an object of type C from the rest of the function arguments std::forward<Args>(args)... with the following equivalent call below after the construction:

If the R satisfies sized_range(until C++26)approximately_sized_range(since C++26) and C satisfies _[reservable-container](#reservable-container)_, the constructed object c of type C is able to reserve storage with the initial storage size ranges::size(r)(until C++26)ranges::reserve_hint(r)(since C++26) to prevent additional allocations during inserting new elements. Each element of r is appended to c.

The operations above are valid if both of the conditions below are true:

  1. Constructs an object of deduced type from the elements of r.

Let /*input-iterator*/ be an exposition only type that satisfies LegacyInputIterator:

Let /*DEDUCE-EXPR*/ be defined as follows:

The call is equivalent to to<decltype(/*DEDUCE-EXPR*/)>
(std::forward<R>(r), std::forward<Args>(args)...).

  1. Is true if it satisfies ranges::sized_range and is eligible to be reservable.

  2. Is true if one element of type Reference can be appended to Container through a member function call emplace_back, push_back, emplace or insert.

  3. Returns a function object where a call to the returned function object is expression-equivalent to appending one element to a container. The return expression is equivalent to:

return [&c]<class Reference>(Reference&& ref)
{
if constexpr (requires { c.emplace_back(std::declval<Reference>()); })
c.emplace_back(std::forward<Reference>(ref));
else if constexpr (requires { c.push_back(std::declval<Reference>()); })
c.push_back(std::forward<Reference>(ref));
else if constexpr (requires { c.emplace(c.end(),
std::declval<Reference>()); })
c.emplace(c.end(), std::forward<Reference>(ref));
else
c.insert(c.end(), std::forward<Reference>(ref));
};

  1. Is used in the definition of containers in constructing an input range R whose range reference type must be convertible to T.

Contents

[edit] Parameters

r - a source range object
args - list of the arguments to (1,2) construct a range or (3,4) bind to the last parameters of range adaptor closure object
Type requirements
-C must be cv-unqualified class type (1,3)

[edit] Return value

1,2) A constructed non-view object.

3,4) A range adaptor closure object of unspecified type, with the following properties:

ranges::to return type

Member objects

The returned object behaves as if it has no target object, and an std::tuple object tup constructed with std::tuple<std::decay_t<Args>...>(std::forward<Args>(args)...), except that the returned object's assignment behavior is unspecified and the names are for exposition only.

Constructors

The return type of ranges::to (3,4) behaves as if its copy/move constructors perform a memberwise copy/move. It is CopyConstructible if all of its member objects (specified above) are CopyConstructible, and is MoveConstructible otherwise.

Member function operator()

Given an object G obtained from an earlier call to range::to</* see below */>(args...), when a glvalue g designating G is invoked in a function call expression g(r), an invocation of the stored object takes place, as if by

The program is ill-formed if g has volatile-qualified type.

[edit] Exceptions

Only throws if construction of a non-view object throws.

[edit] Notes

The insertion of elements into the container may involve copy which can be less efficient than move because lvalue references are produced during the indirection call. Users can opt-in to use views::as_rvalue to adapt the range in order for their elements to always produce an rvalue reference during the indirection call which implies move.

The parentheses are mandatory when using the pipe syntax.

Feature-test macro Value Std Feature
__cpp_lib_ranges_to_container 202202L (C++23) std::ranges::to
__cpp_lib_ranges_reserve_hint 202502L (C++26) ranges::approximately_sized_range, ranges::reserve_hint, and changes to std::ranges::to

[edit] Example

A preview link: Compiler Explorer

#include <boost/container/devector.hpp> #include #include #include #include #include #include #include #include   #ifndef __cpp_lib_format_ranges #include #include   auto print_aid(const auto& v) { std::ostringstream out; out << '['; for (int n{}; const auto& e : v) out << (n++ ? ", " : "") << e; out << ']'; return out; }   template struct std::formatter<std::vector, char> { template constexpr ParseContext::iterator parse(ParseContext& ctx) { return ctx.begin(); }   template FmtContext::iterator format(auto const& s, FmtContext& ctx) const { auto out{print_aid(s)}; return std::ranges::copy(std::move(out).str(), ctx.out()).out; } };   template struct std::formatter<std::list, char> { template constexpr ParseContext::iterator parse(ParseContext& ctx) { return ctx.begin(); }   template FmtContext::iterator format(auto const& s, FmtContext& ctx) const { auto out{print_aid(s)}; return std::ranges::copy(std::move(out).str(), ctx.out()).out; } }; #endif   int main() { auto vec = std::views::iota(1, 5) | std::views::transform([](int v){ return v * 2; }) | std::ranges::to<std::vector>();   static_assert(std::same_as<decltype(vec), std::vector>); std::println("{}", vec);   auto list = vec | std::views::take(3) | std::ranges::to<std::list>(); std::println("{}", list); }   void ctor_demos() { // 1.a.1) Direct init { char array[]{'a', 'b', '\0', 'c'};   // Argument type is convertible to result value type: auto str_to = std::ranges::to<std::string>(array); // Equivalent to std::string str(array);   // Result type is not an input range: auto re_to = std::ranges::to<std::regex>(array); // Equivalent to std::regex re(array); }   // 1.a.2) from_range ctor { auto list = {'a', 'b', '\0', 'c'};   // Argument type is convertible to result value type: auto str_to = std::ranges::to<std::string>(list); // Equivalent to // std::string str(std::from_range, list);   // Result type is not an input range: [[maybe_unused]] auto pair_to = std::ranges::to<std::pair<std::from_range_t, bool>>(true); // Equivalent to std::pair<std::from_range_t, bool> pair(std::from_range, true); }   // 1.a.3) iterator pair ctor { auto list = {'a', 'b', '\0', 'c'};   // Argument type is convertible to result value type: auto devector_to = std::ranges::to<boost:🫙:devector>(list); // Equivalent to boost:🫙:devector devector(std::ranges::begin(list), std::ranges::end(list));   // Result type is not an input range: std::regex re; auto it_to = std::ranges::to<std::cregex_iterator>(list, re); // Equivalent to std::cregex_iterator it(std::ranges::begin(list), std::ranges::end(list), re); } }

Output:

[edit] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
LWG 3984 C++23 the nested construction branch of ranges::to resulted toprogram ill-formed if R& does not model viewable_range made well-formed
LWG 4016 C++23 the container insertion branch ofranges::to involved use of insert iterators replaced with direct appendingof elements to container

[edit] References