ranges::input_range R, class... Args >
requires (!ranges::view<C>)
template< template< class... > class C, class... Args >
constexpr /*range adaptor closure*/ to( Args&&... args );
Helper templates
(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)); } ||
requires { c.insert(c.end(), std::forward<Reference>(ref)); }
);
template< class Reference, class C >
constexpr auto /*container-appender*/( C& c );
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:
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*/)>.
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
.
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));
};
8) Is used in the definition of containers in constructing an input range R
whose range reference type must be convertible to T
.
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 objectsThe 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.
ConstructorsThe 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.
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
input_range
.C
or (4) the deduced type from a class template C
that must not satisfy view
.The program is ill-formed if g has volatile-qualified type.
[edit] ExceptionsOnly throws if construction of a non-view object throws.
[edit] NotesThe 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.
[edit] ExampleA preview link: Compiler Explorer
#include <boost/container/devector.hpp> #include <concepts> #include <initializer_list> #include <list> #include <print> #include <ranges> #include <regex> #include <string> #include <vector> #ifndef __cpp_lib_format_ranges #include <format> #include <sstream> auto print_aid(const auto& v) { std::ostringstream out; out << '['; for (int n{}; const auto& e : v) out << (n++ ? ", " : "") << e; out << ']'; return out; } template<typename T> struct std::formatter<std::vector<T>, char> { template<class ParseContext> constexpr ParseContext::iterator parse(ParseContext& ctx) { return ctx.begin(); } template<class FmtContext> 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<typename T> struct std::formatter<std::list<T>, char> { template<class ParseContext> constexpr ParseContext::iterator parse(ParseContext& ctx) { return ctx.begin(); } template<class FmtContext> 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<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: [[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::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); } }
Output:
[edit] Defect reportsThe 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 ofranges::to
resulted to
R&
does not model viewable_range
made well-formed LWG 4016 C++23 the container insertion branch of
ranges::to
involved use of insert iterators replaced with direct appending
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4