Defined in header
template<classC,ranges::input_rangeR,class...Args>requires(!ranges::view<C>)constexprCto(R&&r,Args&&...args); (1)(since C++23)template<template<class...>classC,ranges::input_rangeR,class...Args>constexprautoto(R&&r,Args&&...args); (2) (since C++23)template<classC,class...Args>requires(!ranges::view<C>)constexpr/*range adaptor closure*/to(Args&&...args); (3)(since C++23)template<template<class...>classC,class...Args>constexpr/*range adaptor closure*/to(Args&&...args); (4) (since C++23)Helper templates
template<classContainer>constexprbool/*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<classContainer,classReference>constexprbool/*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));}||requires{c.insert(c.end(),std::forward<Reference>(ref));});}; (6)(exposition only*)template<classReference,classC>constexprauto/*container-appender*/(C&c); (7)(exposition only*)template<classR,classT>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:
a) If C does not satisfy
or std::convertible_to<ranges::range_reference_t<R>,ranges::range_value_t<C>> is true:
1) Constructing a non-view object as if
(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.
2) Otherwise, constructing a non-view object as if
(but not direct-list-initializing) an object of type C from additional disambiguation tag std::from_range, the source range std::forward<R>(r) and the rest of the functional arguments std::forward<Args>(args)... if std::constructible_from<C,std::from_range_t,R,Args...> is true.
3) Otherwise, constructing a non-view object as if
(but not direct-list-initializing) an object of type C from the iterator-sentinel pair (ranges::begin(r) as an iterator and ranges::end(r) as sentinel, where iterator and sentinel have the same type. In other words, the source range must be a common range), and the rest of function arguments std::forward<Args>(args)... if all of the conditions below are true:
ranges::common_range<R>
If std::iterator_traits<ranges::iterator_t<R>>::iterator_category is valid and denotes a type that satisfies std::derived_from<std::input_iterator_tag>
std::constructible_from<C,ranges::iterator_t<R>,ranges::sentinel_t<R>,Args...>
4) Otherwise, constructing a non-view range object as if
(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:
ifconstexpr(ranges::sized_range<R>&&/*reservable-container*/<C>)
c.reserve(static_cast<ranges::range_size_t<C>>(ranges::size(r)));
ranges::for_each(r,/*container-appender*/(c));
(until C++26)ifconstexpr(ranges::approximately_sized_range<R>
&&/*reservable-container*/<C>)
c.reserve(static_cast<ranges::range_size_t<C>>(ranges::reserve_hint(r)));
ranges::for_each(r,/*container-appender*/(c));
(since C++26)If the R satisfies
(until C++26)
(since C++26) and C satisfies
, 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:
std::constructible_from<C,Args...>
<C,ranges::range_reference_t<R>>
b) Otherwise, the return expression is equivalent to
to<C>(ranges::ref_view(r)|views::transform([](auto&&elem){returnto<ranges::range_value_t<C>>(std::forward<decltype(elem)>(elem));}),std::forward<Args>(args)...)Which allows nested range constructions within the range if ranges::input_range<ranges::range_reference_t<C>> is true.
Otherwise, the program is ill-formed.
2) Constructs an object of deduced type from the elements of r.
Let /*input-iterator*/ be an exposition only type that satisfies
:
struct/*input-iterator*/{usingiterator_category=std::input_iterator_tag;usingvalue_type=ranges::range_value_t<R>;usingdifference_type=std::ptrdiff_t;usingpointer=std::add_pointer_t<ranges::range_reference_t<R>>;usingreference=ranges::range_reference_t<R>;referenceoperator*()const;// not definedpointeroperator->()const;// not defined/*input-iterator*/&operator++();// not defined/*input-iterator*/operator++(int);// not definedbooloperator==(const/*input-iterator*/&)const;// not defined};(exposition only*)Let /*DEDUCE-EXPR*/ be defined as follows:
C(std::declval<R>(),std::declval<Args>()...), if that expression is valid.
Otherwise,
C(std::from_range,std::declval<R>(),
std::declval<Args>()...), if that expression is valid.Otherwise,
C(std::declval</*input-iterator*/>(),
std::declval</*input-iterator*/>(),
std::declval<Args>()...), if that expression is valid.Otherwise, the program is ill-formed.
The call is equivalent to
to<decltype(/*DEDUCE-EXPR*/)>
(std::forward<R>(r),std::forward<Args>(args)...).
5) Is true if it satisfies ranges::sized_range and is eligible to be reservable.
6) 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.
7) 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]<classReference>(Reference&&ref){ifconstexpr(requires{c.emplace_back(std::declval<Reference>());})c.emplace_back(std::forward<Reference>(ref));elseifconstexpr(requires{c.push_back(std::declval<Reference>());})c.push_back(std::forward<Reference>(ref));elseifconstexpr(requires{c.emplace(c.end(),std::declval<Reference>());})c.emplace(c.end(),std::forward<Reference>(ref));elsec.insert(c.end(),std::forward<Reference>(ref));};8) Is used in the definition of containers in constructing an input range R whose range reference type must be convertible to T.
Parameters
r - a source range object args - list of the arguments to (
) construct a range or (
) bind to the last parameters of range adaptor closure object Type requirements -C must be cv-unqualified class type (
)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
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(
) behaves as if its copy/move constructors perform a memberwise copy/move. It is
if all of its member objects (specified above) are CopyConstructible, and is
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
ranges::to</* see below */>(r,std::get<Ns>(g.tup)...), where
r is a source range object that must satisfy
.
Ns is an integer pack 0,1,...,(sizeof...(Args)-1).
g is an lvalue in the call expression if it is an lvalue in the call expression, and is an rvalue otherwise. Thus std::move(g)(r) can move the bound arguments into the call, where g(r) would copy.
The specified template argument is (
)C or (
) the deduced type from a class template C that must not satisfy
.
The program is ill-formed if g has volatile-qualified type.
Exceptions
Only throws if construction of a non-view object throws.
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.
autovec=r|std::ranges::to<std::vector>;// Errorautovec=r|std::ranges::to<std::vector>();// OK
macro ValueStdFeature
(C++23)std::ranges::to
(C++26)ranges::approximately_sized_range, ranges::reserve_hint, and
to std::ranges::toExample
A preview link:
Run this code
#include<boost/container/devector.hpp>#include<concepts>#include<initializer_list>#include<list>#include<print>#include<ranges>#include<regex>#include<string>#include<vector>intmain(){autovec=std::views::iota(1,5)|std::views::transform([](intv){returnv*2;})|std::ranges::to<std::vector>();static_assert(std::same_as<decltype(vec),std::vector<int>>);std::println("1) {}",vec);autolist=vec|std::views::take(3)|std::ranges::to<std::list<double>>();std::println("2) {}",list);}voidctor_demos(){// 1.a.1) Direct init{chararray[]{'a','b','\0','c'};// Argument type is convertible to result value type:autostr_to=std::ranges::to<std::string>(array);// Equivalent tostd::stringstr(array);// Result type is not an input range:autore_to=std::ranges::to<std::regex>(array);// Equivalent tostd::regexre(array);}// 1.a.2) from_range ctor{autolist={'a','b','\0','c'};// Argument type is convertible to result value type:autostr_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]]autopair_to=std::ranges::to<std::pair<std::from_range_t,bool>>(true);// Equivalent tostd::pair<std::from_range_t,bool>pair(std::from_range,true);}// 1.a.3) iterator pair ctor{autolist={'a','b','\0','c'};// Argument type is convertible to result value type:autodevector_to=std::ranges::to<boost::container::devector<char>>(list);// Equivalent toboost::container::devector<char>devector(std::ranges::begin(list),std::ranges::end(list));// Result type is not an input range:std::regexre;autoit_to=std::ranges::to<std::cregex_iterator>(list,re);// Equivalent tostd::cregex_iteratorit(std::ranges::begin(list),std::ranges::end(list),re);}}Output:
1) [2, 4, 6, 8] 2) [2, 4, 6] Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR Applied to Behavior as published Correct behavior
C++23 the nested construction branch of ranges::to resulted to
program ill-formed if R& does not model
made well-formed
C++23 the container insertion branch of
ranges::to involved use of insert iterators replaced with direct appending
of elements to container References
C++23 standard (ISO/IEC 14882:2024):
26.5.7 Range conversions [range.utility.conv]