std::ranges::to
Header: <ranges>
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.
# Declarations
template< class C, ranges::input_range R, class... Args >
requires (!ranges::view<C>)
constexpr C to( R&& r, Args&&... args );
(since C++23)
template< template< class... > class C,
ranges::input_range R, class... Args >
constexpr auto to( R&& r, Args&&... args );
(since C++23)
template< class C, class... Args >
requires (!ranges::view<C>)
constexpr /*range adaptor closure*/ to( Args&&... args );
(since C++23)
template< template< class... > class C, class... Args >
constexpr /*range adaptor closure*/ to( Args&&... args );
(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)>;
};
(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)); } ||
requires { c.insert(c.end(), std::forward<Reference>(ref)); }
);
};
(exposition only*)
template< class Reference, class C >
constexpr auto /*container-appender*/( C& c );
(exposition only*)
template< class R, class T >
concept /*container-compatible-range*/ =
ranges::input_range<R> &&
std::convertible_to<ranges::range_reference_t<R>, T>;
(exposition only*)
# Parameters
r: a source range objectargs: list of the arguments to (1,2) construct a range or (3,4) bind to the last parameters of range adaptor closure object
# Return value
The returned object behaves as if it has no target object, and an std::tuple object tup constructed with std::tuple<std::decay_t
# 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.
# Example
#include <boost/container/devector.hpp>
#include <concepts>
#include <list>
#include <initializer_list>
#include <iostream>
#include <print>
#include <ranges>
#include <regex>
#include <string>
#include <vector>
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<int>>);
std::println("{}", vec);
auto list = vec | std::views::take(3) | std::ranges::to<std::list<double>>();
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:
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::container::devector<char>>(list);
// Equivalent to
boost::container::devector<char> 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);
}
}
# Defect reports
| 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 |